Skip to content

Commit 309dc23

Browse files
BarbatosBarbatos
authored andcommitted
test(plugins): improve coverage for keystore validation and edge cases
- Add tests for update with nonexistent/file keystore-dir, old Mac CR line endings, and invalid-version keystore files - Add test for import duplicate check skipping invalid-version files - Add test for list skipping invalid-version and no-crypto keystores - Fix password file split regex to handle old Mac CR-only line endings
1 parent 1f27bca commit 309dc23

4 files changed

Lines changed: 166 additions & 1 deletion

File tree

plugins/src/main/java/common/org/tron/plugins/KeystoreUpdate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public Integer call() {
8282
if (content.length() > 0 && content.charAt(0) == '\uFEFF') {
8383
content = content.substring(1);
8484
}
85-
String[] lines = content.split("\\r?\\n");
85+
String[] lines = content.split("\\r?\\n|\\r");
8686
if (lines.length < 2) {
8787
err.println(
8888
"Password file must contain old and new passwords"

plugins/src/test/java/org/tron/plugins/KeystoreImportTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,4 +373,33 @@ public void testImportKeystoreFilePermissions() throws Exception {
373373
java.nio.file.attribute.PosixFilePermission.OWNER_WRITE),
374374
perms);
375375
}
376+
377+
@Test
378+
public void testImportDuplicateCheckSkipsInvalidVersion() throws Exception {
379+
File dir = tempFolder.newFolder("keystore-badver");
380+
SignInterface keyPair = SignUtils.getGeneratedRandomSign(
381+
SecureRandom.getInstance("NativePRNG"), true);
382+
String privateKeyHex = ByteArray.toHexString(keyPair.getPrivateKey());
383+
String address = Credentials.create(keyPair).getAddress();
384+
385+
// Create a JSON with correct address but wrong version — should NOT count as duplicate
386+
String fakeKeystore = "{\"address\":\"" + address
387+
+ "\",\"version\":2,\"crypto\":{\"cipher\":\"aes-128-ctr\"}}";
388+
Files.write(new File(dir, "fake.json").toPath(),
389+
fakeKeystore.getBytes(StandardCharsets.UTF_8));
390+
391+
File keyFile = tempFolder.newFile("ver.key");
392+
Files.write(keyFile.toPath(), privateKeyHex.getBytes(StandardCharsets.UTF_8));
393+
File pwFile = tempFolder.newFile("pw-ver.txt");
394+
Files.write(pwFile.toPath(), "test123456".getBytes(StandardCharsets.UTF_8));
395+
396+
CommandLine cmd = new CommandLine(new Toolkit());
397+
int exitCode = cmd.execute("keystore", "import",
398+
"--keystore-dir", dir.getAbsolutePath(),
399+
"--key-file", keyFile.getAbsolutePath(),
400+
"--password-file", pwFile.getAbsolutePath());
401+
402+
assertEquals("Import should succeed — invalid-version file is not a real duplicate", 0,
403+
exitCode);
404+
}
376405
}

plugins/src/test/java/org/tron/plugins/KeystoreListTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,38 @@ public void testListWarnsOnCorruptedJsonFiles() throws Exception {
206206
String output = out.toString().trim();
207207
assertTrue("Should still list the valid keystore", output.length() > 0);
208208
}
209+
210+
@Test
211+
public void testListSkipsInvalidVersionKeystores() throws Exception {
212+
File dir = tempFolder.newFolder("keystore-version");
213+
String password = "test123456";
214+
215+
// Create one valid keystore
216+
SignInterface key = SignUtils.getGeneratedRandomSign(
217+
SecureRandom.getInstance("NativePRNG"), true);
218+
WalletUtils.generateWalletFile(password, key, dir, false);
219+
220+
// Create a JSON with address and crypto but wrong version
221+
String fakeV2 = "{\"address\":\"TFakeAddress\",\"version\":2,"
222+
+ "\"crypto\":{\"cipher\":\"aes-128-ctr\"}}";
223+
Files.write(new File(dir, "v2-keystore.json").toPath(),
224+
fakeV2.getBytes(StandardCharsets.UTF_8));
225+
226+
// Create a JSON with address but null crypto
227+
String noCrypto = "{\"address\":\"TFakeAddress2\",\"version\":3}";
228+
Files.write(new File(dir, "no-crypto.json").toPath(),
229+
noCrypto.getBytes(StandardCharsets.UTF_8));
230+
231+
StringWriter out = new StringWriter();
232+
CommandLine cmd = new CommandLine(new Toolkit());
233+
cmd.setOut(new PrintWriter(out));
234+
int exitCode = cmd.execute("keystore", "list",
235+
"--keystore-dir", dir.getAbsolutePath());
236+
237+
assertEquals(0, exitCode);
238+
String output = out.toString().trim();
239+
String[] lines = output.split("\\n");
240+
assertEquals("Should list only the valid v3 keystore, not v2 or no-crypto",
241+
1, lines.length);
242+
}
209243
}

plugins/src/test/java/org/tron/plugins/KeystoreUpdateTest.java

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,4 +446,106 @@ public void testUpdatePasswordFileWithBom() throws Exception {
446446
assertArrayEquals("Key must survive update with BOM password file",
447447
originalKey, updated.getSignInterface().getPrivateKey());
448448
}
449+
450+
@Test
451+
public void testUpdateNonExistentKeystoreDir() throws Exception {
452+
File dir = new File(tempFolder.getRoot(), "does-not-exist");
453+
454+
File pwFile = tempFolder.newFile("pw-nodir.txt");
455+
Files.write(pwFile.toPath(),
456+
("oldpass123\nnewpass456").getBytes(StandardCharsets.UTF_8));
457+
458+
StringWriter err = new StringWriter();
459+
CommandLine cmd = new CommandLine(new Toolkit());
460+
cmd.setErr(new PrintWriter(err));
461+
int exitCode = cmd.execute("keystore", "update", "TSomeAddress",
462+
"--keystore-dir", dir.getAbsolutePath(),
463+
"--password-file", pwFile.getAbsolutePath());
464+
465+
assertEquals(1, exitCode);
466+
assertTrue("Error should mention no keystore found",
467+
err.toString().contains("No keystore found for address"));
468+
}
469+
470+
@Test
471+
public void testUpdateKeystoreDirIsFile() throws Exception {
472+
File notADir = tempFolder.newFile("not-a-dir");
473+
474+
File pwFile = tempFolder.newFile("pw-notdir.txt");
475+
Files.write(pwFile.toPath(),
476+
("oldpass123\nnewpass456").getBytes(StandardCharsets.UTF_8));
477+
478+
StringWriter err = new StringWriter();
479+
CommandLine cmd = new CommandLine(new Toolkit());
480+
cmd.setErr(new PrintWriter(err));
481+
int exitCode = cmd.execute("keystore", "update", "TSomeAddress",
482+
"--keystore-dir", notADir.getAbsolutePath(),
483+
"--password-file", pwFile.getAbsolutePath());
484+
485+
assertEquals(1, exitCode);
486+
assertTrue("Error should mention no keystore found",
487+
err.toString().contains("No keystore found for address"));
488+
}
489+
490+
@Test
491+
public void testUpdateWithOldMacLineEndings() throws Exception {
492+
File dir = tempFolder.newFolder("keystore-cr");
493+
String oldPassword = "oldpass123";
494+
String newPassword = "newpass456";
495+
496+
SignInterface keyPair = SignUtils.getGeneratedRandomSign(
497+
SecureRandom.getInstance("NativePRNG"), true);
498+
byte[] originalKey = keyPair.getPrivateKey();
499+
String fileName = WalletUtils.generateWalletFile(oldPassword, keyPair, dir, true);
500+
Credentials creds = WalletUtils.loadCredentials(oldPassword,
501+
new File(dir, fileName), true);
502+
503+
// Password file with old Mac line endings (\r only)
504+
File pwFile = tempFolder.newFile("cr.txt");
505+
Files.write(pwFile.toPath(),
506+
(oldPassword + "\r" + newPassword + "\r").getBytes(StandardCharsets.UTF_8));
507+
508+
CommandLine cmd = new CommandLine(new Toolkit());
509+
int exitCode = cmd.execute("keystore", "update", creds.getAddress(),
510+
"--keystore-dir", dir.getAbsolutePath(),
511+
"--password-file", pwFile.getAbsolutePath());
512+
513+
assertEquals("Update with old Mac CR line endings should succeed", 0, exitCode);
514+
515+
Credentials updated = WalletUtils.loadCredentials(newPassword,
516+
new File(dir, fileName), true);
517+
assertArrayEquals("Key must survive update with CR passwords",
518+
originalKey, updated.getSignInterface().getPrivateKey());
519+
}
520+
521+
@Test
522+
public void testUpdateSkipsInvalidVersionKeystores() throws Exception {
523+
File dir = tempFolder.newFolder("keystore-badver");
524+
String password = "test123456";
525+
526+
SignInterface keyPair = SignUtils.getGeneratedRandomSign(
527+
SecureRandom.getInstance("NativePRNG"), true);
528+
String address = Credentials.create(keyPair).getAddress();
529+
530+
// Create a JSON file with correct address but wrong version
531+
String fakeKeystore = "{\"address\":\"" + address
532+
+ "\",\"version\":2,\"crypto\":{\"cipher\":\"aes-128-ctr\"}}";
533+
Files.write(new File(dir, "fake.json").toPath(),
534+
fakeKeystore.getBytes(StandardCharsets.UTF_8));
535+
536+
File pwFile = tempFolder.newFile("pw-badver.txt");
537+
Files.write(pwFile.toPath(),
538+
(password + "\nnewpass789").getBytes(StandardCharsets.UTF_8));
539+
540+
StringWriter err = new StringWriter();
541+
CommandLine cmd = new CommandLine(new Toolkit());
542+
cmd.setErr(new PrintWriter(err));
543+
int exitCode = cmd.execute("keystore", "update", address,
544+
"--keystore-dir", dir.getAbsolutePath(),
545+
"--password-file", pwFile.getAbsolutePath());
546+
547+
assertEquals("Should not find keystore with wrong version", 1, exitCode);
548+
assertTrue("Error should mention no keystore found",
549+
err.toString().contains("No keystore found"));
550+
}
449551
}

0 commit comments

Comments
 (0)