Skip to content

Commit eb6b5cd

Browse files
author
jennnijuju
committed
Added tests for the signature signer verifier.
jars are brought to the project for the test only.
1 parent 7df525f commit eb6b5cd

File tree

9 files changed

+230
-2
lines changed

9 files changed

+230
-2
lines changed

build.xml

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,51 @@
88
<property name="built-sources" value="${build-dir}/main"/>
99
<property name="built-jar" value="${workspace}/dist"/>
1010
<property name="jar-name" value="offline-signer"/>
11-
11+
12+
<property name="test" value="${workspace}/test"/>
13+
<property name="test-reports" value="${workspace}/reports"/>
14+
<property name="built-tests" value="${build-dir}/test"/>
15+
16+
<path id="classpath-test">
17+
<pathelement location="${dependencies}/aion-types-22a3be9.jar"/>
18+
<pathelement location="${dependencies}/util4j-674e4b5.jar"/>
19+
<pathelement location="${dependencies}/guava-25.1-jre.jar"/>
20+
<pathelement location="${dependencies}/junit-4.12.jar"/>
21+
<pathelement location="${dependencies}/hamcrest-all-1.3.jar"/>
22+
<pathelement location="${dependencies}/ed25519.jar"/>
23+
<pathelement location="${dependencies}/modRlp.jar"/>
24+
</path>
25+
1226
<target name="clean_build" depends="clean, build"/>
27+
28+
<target name="test_build" depends="clean_build">
29+
<mkdir dir="${built-tests}"/>
30+
31+
<javac debug="true" debuglevel="source,lines,vars" includeantruntime="false" release="10"
32+
srcdir="${test}" destdir="${built-tests}" includes="**/*.java,module-info.java">
33+
<classpath>
34+
<pathelement location="${built-sources}"/>
35+
<path refid="classpath-test"/>
36+
</classpath>
37+
</javac>
38+
</target>
39+
40+
41+
<target name="test" depends="test_build">
42+
<mkdir dir="${test-reports}"/>
43+
<junit printsummary="on" haltonfailure="true" fork="true" dir="${workspace}">
44+
<classpath>
45+
<pathelement location="${built-sources}"/>
46+
<pathelement location="${built-tests}"/>
47+
<path refid="classpath-test"/>
48+
</classpath>
49+
<formatter type="plain" usefile="false"/>
50+
<formatter type="xml"/>
51+
<batchtest todir="${test-reports}">
52+
<fileset dir="${test}" includes="**/*Test.java"/>
53+
</batchtest>
54+
</junit>
55+
</target>
1356

1457
<target name="build">
1558
<mkdir dir="${built-sources}"/>

lib/aion-types-22a3be9.jar

14.5 KB
Binary file not shown.

lib/guava-25.1-jre.jar

2.61 MB
Binary file not shown.

lib/hamcrest-all-1.3.jar

299 KB
Binary file not shown.

lib/junit-4.12.jar

308 KB
Binary file not shown.

lib/util4j-674e4b5.jar

77.1 KB
Binary file not shown.

src/module-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
requires aion.rlp;
44

55
exports main;
6-
}
6+
}

test/main/PrivateKey.java

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package main;
2+
3+
import main.crypto.Blake2b;
4+
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
5+
import net.i2p.crypto.eddsa.KeyPairGenerator;
6+
import net.i2p.crypto.eddsa.Utils;
7+
import org.aion.util.conversions.Hex;
8+
import java.nio.ByteBuffer;
9+
import java.security.KeyPair;
10+
import java.security.spec.InvalidKeySpecException;
11+
import java.security.spec.PKCS8EncodedKeySpec;
12+
import java.util.Arrays;
13+
14+
15+
public final class PrivateKey {
16+
public static final int SIZE = 32;
17+
18+
private final byte[] key;
19+
private final byte[] address;
20+
21+
/**
22+
* Constructs a new private key consisting of the provided bytes.
23+
*
24+
* @param privateKeyBytes The bytes of the private key.
25+
*/
26+
private PrivateKey(byte[] privateKeyBytes) throws InvalidKeySpecException {
27+
if (privateKeyBytes == null) {
28+
throw new NullPointerException("private key bytes cannot be null");
29+
}
30+
if (privateKeyBytes.length != SIZE) {
31+
throw new IllegalArgumentException("bytes of a private key must have a length of " + SIZE);
32+
}
33+
this.key = privateKeyBytes.clone();
34+
this.address = deriveAddress(this.key);
35+
}
36+
37+
public static PrivateKey fromBytes(byte[] privateKeyBytes) throws InvalidKeySpecException {
38+
return new PrivateKey(privateKeyBytes);
39+
}
40+
41+
public static PrivateKey random() {
42+
try {
43+
return new PrivateKey(generatePrivateKey());
44+
} catch (InvalidKeySpecException e) {
45+
// Hiding the checked exception because this should never actually happen here. We have
46+
// complete control over these bytes and know they are generated in a sound way.
47+
throw new RuntimeException(e.getMessage());
48+
}
49+
}
50+
51+
public byte[] copyOfUnderlyingBytes() {
52+
return this.key.clone();
53+
}
54+
55+
public byte[] getPublicAionAddress() {
56+
return this.address;
57+
}
58+
59+
@Override
60+
public String toString() {
61+
return "com.theoan.transactionbuilder.main.PrivateKey { 0x" + Hex.toHexString(this.key) + " }";
62+
}
63+
64+
/**
65+
* Returns true only if other is a com.theoan.transactionbuilder.main.PrivateKey with the same underlying bytes.
66+
*
67+
* @param other The other whose equality is to be tested.
68+
* @return whether this is equal to other.
69+
*/
70+
@Override
71+
public boolean equals(Object other) {
72+
if (!(other instanceof PrivateKey)) {
73+
return false;
74+
} else if (other == this) {
75+
return true;
76+
}
77+
return Arrays.equals(this.key, ((PrivateKey) other).key);
78+
}
79+
80+
@Override
81+
public int hashCode() {
82+
return Arrays.hashCode(this.key);
83+
}
84+
85+
public static byte[] generatePrivateKey() {
86+
KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
87+
KeyPair pair = keyPairGenerator.generateKeyPair();
88+
EdDSAPrivateKey privateKey = (EdDSAPrivateKey) pair.getPrivate();
89+
return Utils.hexToBytes(Utils.bytesToHex(privateKey.getEncoded()).substring(32, 96));
90+
}
91+
92+
private static byte[] deriveAddress(byte[] privateKeyBytes) throws InvalidKeySpecException {
93+
if (privateKeyBytes == null) {
94+
throw new NullPointerException("private key cannot be null");
95+
}
96+
97+
if (privateKeyBytes.length != 32){
98+
throw new IllegalArgumentException("private key mute be 32 bytes");
99+
}
100+
101+
EdDSAPrivateKey privateKey = new EdDSAPrivateKey(new PKCS8EncodedKeySpec(addSkPrefix(Utils.bytesToHex(privateKeyBytes))));
102+
byte[] publicKeyBytes = privateKey.getAbyte();
103+
104+
return computeA0Address(publicKeyBytes);
105+
}
106+
107+
private static byte[] addSkPrefix(String skString){
108+
String skEncoded = "302e020100300506032b657004220420" + skString;
109+
return Utils.hexToBytes(skEncoded);
110+
}
111+
112+
private static byte[] computeA0Address(byte[] publicKey) {
113+
byte A0_IDENTIFIER = (byte) 0xa0;
114+
ByteBuffer buf = ByteBuffer.allocate(32);
115+
buf.put(A0_IDENTIFIER);
116+
buf.put(blake256(publicKey), 1, 31);
117+
return buf.array();
118+
}
119+
120+
private static byte[] blake256(byte[] input) {
121+
Blake2b digest = Blake2b.Digest.newInstance(32);
122+
digest.update(input);
123+
return digest.digest();
124+
}
125+
}

test/main/VerifierTest.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
6+
import java.math.BigInteger;
7+
8+
public class VerifierTest {
9+
@Test
10+
public void testMatchedSignerRegular() throws Exception{
11+
PrivateKey random = PrivateKey.random();
12+
byte[] signed = getSignedTransaction(random);
13+
Assert.assertTrue(SignedTransactionVerifier.isSignerForRegularTransaction(signed, random.getPublicAionAddress()));
14+
15+
}
16+
17+
@Test
18+
public void testUnMatchedSignerRegular() throws Exception{
19+
PrivateKey expectedSigner = PrivateKey.random();
20+
PrivateKey otherSigner = PrivateKey.random();
21+
byte[] signed = getSignedTransaction(expectedSigner);
22+
Assert.assertFalse(SignedTransactionVerifier.isSignerForRegularTransaction(signed, otherSigner.copyOfUnderlyingBytes()));
23+
24+
}
25+
26+
@Test
27+
public void testMatchedSignerInvokable() throws Exception{
28+
PrivateKey random = PrivateKey.random();
29+
byte[] signed = getSignedInvokable(random);
30+
Assert.assertTrue(SignedTransactionVerifier.isSignerForInvokableTransaction(signed, random.getPublicAionAddress()));
31+
32+
}
33+
34+
@Test
35+
public void testUnMatchedSignerInvokable() throws Exception{
36+
PrivateKey expectedSigner = PrivateKey.random();
37+
PrivateKey otherSigner = PrivateKey.random();
38+
byte[] signed = getSignedInvokable(expectedSigner);
39+
Assert.assertFalse(SignedTransactionVerifier.isSignerForInvokableTransaction(signed, otherSigner.copyOfUnderlyingBytes()));
40+
41+
}
42+
43+
private byte[] getSignedInvokable(PrivateKey privateKey) throws Exception {
44+
return new SignedInvokableTransactionBuilder().privateKey(privateKey.copyOfUnderlyingBytes())
45+
.executor(PrivateKey.random().getPublicAionAddress())
46+
.data(new byte[32])
47+
.destination(PrivateKey.random().getPublicAionAddress())
48+
.senderNonce(BigInteger.ZERO)
49+
.buildSignedInvokableTransaction();
50+
}
51+
52+
private byte[] getSignedTransaction(PrivateKey privateKey) throws Exception {
53+
return new SignedTransactionBuilder().privateKey(privateKey.copyOfUnderlyingBytes())
54+
.data(new byte[0])
55+
.energyLimit(200000)
56+
.energyPrice(10000000000L)
57+
.senderNonce(BigInteger.ZERO)
58+
.buildSignedTransaction();
59+
}
60+
}

0 commit comments

Comments
 (0)