33import static org .junit .Assert .assertArrayEquals ;
44import static org .junit .Assert .assertEquals ;
55import static org .junit .Assert .assertNotNull ;
6+ import static org .junit .Assert .assertTrue ;
67
78import com .fasterxml .jackson .databind .DeserializationFeature ;
89import com .fasterxml .jackson .databind .ObjectMapper ;
910import java .io .File ;
11+ import org .junit .Rule ;
1012import org .junit .Test ;
13+ import org .junit .rules .TemporaryFolder ;
1114import org .tron .common .crypto .SignInterface ;
1215import org .tron .common .crypto .SignUtils ;
1316import org .tron .common .utils .Utils ;
1417
1518/**
16- * Cross-implementation compatibility tests.
17- * Verifies that keystore files can survive a roundtrip through the
18- * Java implementation (encrypt → serialize → deserialize → decrypt).
19+ * Format compatibility tests.
1920 *
20- * Also verifies that keystore files generated by legacy --keystore-factory
21- * code are compatible with the new library.
21+ * <p>All tests generate keystores dynamically at test time — no static
22+ * fixtures or secrets stored in the repository. Verifies that keystore
23+ * files can survive a full roundtrip: generate keypair, encrypt, serialize
24+ * to JSON file, deserialize, decrypt, compare private key and address.
2225 */
2326public class CrossImplTest {
2427
2528 private static final ObjectMapper MAPPER = new ObjectMapper ()
2629 .configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
2730
31+ @ Rule
32+ public TemporaryFolder tempFolder = new TemporaryFolder ();
33+
34+ // --- Ethereum standard test vectors (from Web3 Secret Storage spec, inline) ---
35+ // Source: web3j WalletTest.java — password and private key are public test data.
36+
37+ private static final String ETH_PASSWORD = "Insecure Pa55w0rd" ;
38+ private static final String ETH_PRIVATE_KEY =
39+ "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6" ;
40+
41+ private static final String ETH_PBKDF2_KEYSTORE = "{"
42+ + "\" crypto\" :{\" cipher\" :\" aes-128-ctr\" ,"
43+ + "\" cipherparams\" :{\" iv\" :\" 02ebc768684e5576900376114625ee6f\" },"
44+ + "\" ciphertext\" :\" 7ad5c9dd2c95f34a92ebb86740b92103a5d1cc4c2eabf3b9a59e1f83f3181216\" ,"
45+ + "\" kdf\" :\" pbkdf2\" ,"
46+ + "\" kdfparams\" :{\" c\" :262144,\" dklen\" :32,\" prf\" :\" hmac-sha256\" ,"
47+ + "\" salt\" :\" 0e4cf3893b25bb81efaae565728b5b7cde6a84e224cbf9aed3d69a31c981b702\" },"
48+ + "\" mac\" :\" 2b29e4641ec17f4dc8b86fc8592090b50109b372529c30b001d4d96249edaf62\" },"
49+ + "\" id\" :\" af0451b4-6020-4ef0-91ec-794a5a965b01\" ,\" version\" :3}" ;
50+
51+ private static final String ETH_SCRYPT_KEYSTORE = "{"
52+ + "\" crypto\" :{\" cipher\" :\" aes-128-ctr\" ,"
53+ + "\" cipherparams\" :{\" iv\" :\" 3021e1ef4774dfc5b08307f3a4c8df00\" },"
54+ + "\" ciphertext\" :\" 4dd29ba18478b98cf07a8a44167acdf7e04de59777c4b9c139e3d3fa5cb0b931\" ,"
55+ + "\" kdf\" :\" scrypt\" ,"
56+ + "\" kdfparams\" :{\" dklen\" :32,\" n\" :262144,\" r\" :8,\" p\" :1,"
57+ + "\" salt\" :\" 4f9f68c71989eb3887cd947c80b9555fce528f210199d35c35279beb8c2da5ca\" },"
58+ + "\" mac\" :\" 7e8f2192767af9be18e7a373c1986d9190fcaa43ad689bbb01a62dbde159338d\" },"
59+ + "\" id\" :\" 7654525c-17e0-4df5-94b5-c7fde752c9d2\" ,\" version\" :3}" ;
60+
61+ @ Test
62+ public void testDecryptEthPbkdf2Keystore () throws Exception {
63+ WalletFile walletFile = MAPPER .readValue (ETH_PBKDF2_KEYSTORE , WalletFile .class );
64+ SignInterface recovered = Wallet .decrypt (ETH_PASSWORD , walletFile , true );
65+ assertEquals ("Private key must match Ethereum test vector" ,
66+ ETH_PRIVATE_KEY ,
67+ org .tron .common .utils .ByteArray .toHexString (recovered .getPrivateKey ()));
68+ }
69+
2870 @ Test
29- public void testLightKeystoreRoundtrip () throws Exception {
30- String password = "testpassword123" ;
71+ public void testDecryptEthScryptKeystore () throws Exception {
72+ WalletFile walletFile = MAPPER .readValue (ETH_SCRYPT_KEYSTORE , WalletFile .class );
73+ SignInterface recovered = Wallet .decrypt (ETH_PASSWORD , walletFile , true );
74+ assertEquals ("Private key must match Ethereum test vector" ,
75+ ETH_PRIVATE_KEY ,
76+ org .tron .common .utils .ByteArray .toHexString (recovered .getPrivateKey ()));
77+ }
78+
79+ // --- Dynamic format compatibility (no static secrets) ---
80+
81+ @ Test
82+ public void testKeystoreFormatCompatibility () throws Exception {
3183 SignInterface keyPair = SignUtils .getGeneratedRandomSign (Utils .getRandom (), true );
3284 byte [] originalKey = keyPair .getPrivateKey ();
85+ String password = "dynamicTest123" ;
3386
34- // Create keystore → write to temp file → read back → decrypt
35- WalletFile walletFile = Wallet .createLight (password , keyPair );
36- File tempFile = File .createTempFile ("keystore-test-" , ".json" );
37- tempFile .deleteOnExit ();
38- MAPPER .writeValue (tempFile , walletFile );
87+ WalletFile walletFile = Wallet .createStandard (password , keyPair );
3988
89+ // Verify Web3 Secret Storage structure
90+ assertEquals ("version must be 3" , 3 , walletFile .getVersion ());
91+ assertNotNull ("must have address" , walletFile .getAddress ());
92+ assertNotNull ("must have crypto" , walletFile .getCrypto ());
93+ assertEquals ("cipher must be aes-128-ctr" ,
94+ "aes-128-ctr" , walletFile .getCrypto ().getCipher ());
95+ assertTrue ("kdf must be scrypt or pbkdf2" ,
96+ "scrypt" .equals (walletFile .getCrypto ().getKdf ())
97+ || "pbkdf2" .equals (walletFile .getCrypto ().getKdf ()));
98+
99+ // Write to file, read back — simulates cross-process interop
100+ File tempFile = new File (tempFolder .getRoot (), "compat-test.json" );
101+ MAPPER .writeValue (tempFile , walletFile );
40102 WalletFile loaded = MAPPER .readValue (tempFile , WalletFile .class );
41- SignInterface recovered = Wallet .decrypt (password , loaded , true );
42103
43- assertArrayEquals ("File roundtrip must preserve private key" ,
104+ SignInterface recovered = Wallet .decrypt (password , loaded , true );
105+ assertArrayEquals ("Key must survive file roundtrip" ,
44106 originalKey , recovered .getPrivateKey ());
107+
108+ // Verify TRON address format
109+ byte [] tronAddr = recovered .getAddress ();
110+ assertEquals ("TRON address must be 21 bytes" , 21 , tronAddr .length );
111+ assertEquals ("First byte must be TRON prefix" , 0x41 , tronAddr [0 ] & 0xFF );
45112 }
46113
47114 @ Test
48- public void testStandardKeystoreRoundtrip () throws Exception {
49- String password = "testpassword456" ;
115+ public void testLightScryptFormatCompatibility () throws Exception {
50116 SignInterface keyPair = SignUtils .getGeneratedRandomSign (Utils .getRandom (), true );
51117 byte [] originalKey = keyPair .getPrivateKey ();
118+ String password = "lightCompat456" ;
52119
53- WalletFile walletFile = Wallet .createStandard (password , keyPair );
54- File tempFile = File .createTempFile ("keystore-std-" , ".json" );
55- tempFile .deleteOnExit ();
120+ WalletFile walletFile = Wallet .createLight (password , keyPair );
121+ File tempFile = new File (tempFolder .getRoot (), "light-compat.json" );
56122 MAPPER .writeValue (tempFile , walletFile );
57-
58123 WalletFile loaded = MAPPER .readValue (tempFile , WalletFile .class );
59- SignInterface recovered = Wallet .decrypt (password , loaded , true );
60124
61- assertArrayEquals ("Standard scrypt file roundtrip must preserve private key" ,
125+ SignInterface recovered = Wallet .decrypt (password , loaded , true );
126+ assertArrayEquals ("Key must survive light scrypt file roundtrip" ,
62127 originalKey , recovered .getPrivateKey ());
63128 }
64129
@@ -85,30 +150,16 @@ public void testLoadCredentialsIntegration() throws Exception {
85150 byte [] originalKey = keyPair .getPrivateKey ();
86151 String originalAddress = Credentials .create (keyPair ).getAddress ();
87152
88- // Use WalletUtils full flow
89- File tempDir = new File (System .getProperty ("java.io.tmpdir" ), "keystore-test-" +
90- System .currentTimeMillis ());
91- tempDir .mkdirs ();
92- try {
93- String fileName = WalletUtils .generateWalletFile (password , keyPair , tempDir , false );
94- assertNotNull (fileName );
95-
96- File keystoreFile = new File (tempDir , fileName );
97- Credentials loaded = WalletUtils .loadCredentials (password , keystoreFile , true );
98-
99- assertEquals ("Address must survive full WalletUtils roundtrip" ,
100- originalAddress , loaded .getAddress ());
101- assertArrayEquals ("Key must survive full WalletUtils roundtrip" ,
102- originalKey , loaded .getSignInterface ().getPrivateKey ());
103- } finally {
104- // Cleanup
105- File [] files = tempDir .listFiles ();
106- if (files != null ) {
107- for (File f : files ) {
108- f .delete ();
109- }
110- }
111- tempDir .delete ();
112- }
153+ File tempDir = tempFolder .newFolder ("wallet-integration" );
154+ String fileName = WalletUtils .generateWalletFile (password , keyPair , tempDir , false );
155+ assertNotNull (fileName );
156+
157+ File keystoreFile = new File (tempDir , fileName );
158+ Credentials loaded = WalletUtils .loadCredentials (password , keystoreFile , true );
159+
160+ assertEquals ("Address must survive full WalletUtils roundtrip" ,
161+ originalAddress , loaded .getAddress ());
162+ assertArrayEquals ("Key must survive full WalletUtils roundtrip" ,
163+ originalKey , loaded .getSignInterface ().getPrivateKey ());
113164 }
114165}
0 commit comments