-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added tests for the signature signer verifier.
jars are brought to the project for the test only.
- Loading branch information
jennnijuju
committed
Dec 18, 2019
1 parent
7df525f
commit eb6b5cd
Showing
9 changed files
with
230 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,4 @@ | |
requires aion.rlp; | ||
|
||
exports main; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package main; | ||
|
||
import main.crypto.Blake2b; | ||
import net.i2p.crypto.eddsa.EdDSAPrivateKey; | ||
import net.i2p.crypto.eddsa.KeyPairGenerator; | ||
import net.i2p.crypto.eddsa.Utils; | ||
import org.aion.util.conversions.Hex; | ||
import java.nio.ByteBuffer; | ||
import java.security.KeyPair; | ||
import java.security.spec.InvalidKeySpecException; | ||
import java.security.spec.PKCS8EncodedKeySpec; | ||
import java.util.Arrays; | ||
|
||
|
||
public final class PrivateKey { | ||
public static final int SIZE = 32; | ||
|
||
private final byte[] key; | ||
private final byte[] address; | ||
|
||
/** | ||
* Constructs a new private key consisting of the provided bytes. | ||
* | ||
* @param privateKeyBytes The bytes of the private key. | ||
*/ | ||
private PrivateKey(byte[] privateKeyBytes) throws InvalidKeySpecException { | ||
if (privateKeyBytes == null) { | ||
throw new NullPointerException("private key bytes cannot be null"); | ||
} | ||
if (privateKeyBytes.length != SIZE) { | ||
throw new IllegalArgumentException("bytes of a private key must have a length of " + SIZE); | ||
} | ||
this.key = privateKeyBytes.clone(); | ||
this.address = deriveAddress(this.key); | ||
} | ||
|
||
public static PrivateKey fromBytes(byte[] privateKeyBytes) throws InvalidKeySpecException { | ||
return new PrivateKey(privateKeyBytes); | ||
} | ||
|
||
public static PrivateKey random() { | ||
try { | ||
return new PrivateKey(generatePrivateKey()); | ||
} catch (InvalidKeySpecException e) { | ||
// Hiding the checked exception because this should never actually happen here. We have | ||
// complete control over these bytes and know they are generated in a sound way. | ||
throw new RuntimeException(e.getMessage()); | ||
} | ||
} | ||
|
||
public byte[] copyOfUnderlyingBytes() { | ||
return this.key.clone(); | ||
} | ||
|
||
public byte[] getPublicAionAddress() { | ||
return this.address; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "com.theoan.transactionbuilder.main.PrivateKey { 0x" + Hex.toHexString(this.key) + " }"; | ||
} | ||
|
||
/** | ||
* Returns true only if other is a com.theoan.transactionbuilder.main.PrivateKey with the same underlying bytes. | ||
* | ||
* @param other The other whose equality is to be tested. | ||
* @return whether this is equal to other. | ||
*/ | ||
@Override | ||
public boolean equals(Object other) { | ||
if (!(other instanceof PrivateKey)) { | ||
return false; | ||
} else if (other == this) { | ||
return true; | ||
} | ||
return Arrays.equals(this.key, ((PrivateKey) other).key); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Arrays.hashCode(this.key); | ||
} | ||
|
||
public static byte[] generatePrivateKey() { | ||
KeyPairGenerator keyPairGenerator = new KeyPairGenerator(); | ||
KeyPair pair = keyPairGenerator.generateKeyPair(); | ||
EdDSAPrivateKey privateKey = (EdDSAPrivateKey) pair.getPrivate(); | ||
return Utils.hexToBytes(Utils.bytesToHex(privateKey.getEncoded()).substring(32, 96)); | ||
} | ||
|
||
private static byte[] deriveAddress(byte[] privateKeyBytes) throws InvalidKeySpecException { | ||
if (privateKeyBytes == null) { | ||
throw new NullPointerException("private key cannot be null"); | ||
} | ||
|
||
if (privateKeyBytes.length != 32){ | ||
throw new IllegalArgumentException("private key mute be 32 bytes"); | ||
} | ||
|
||
EdDSAPrivateKey privateKey = new EdDSAPrivateKey(new PKCS8EncodedKeySpec(addSkPrefix(Utils.bytesToHex(privateKeyBytes)))); | ||
byte[] publicKeyBytes = privateKey.getAbyte(); | ||
|
||
return computeA0Address(publicKeyBytes); | ||
} | ||
|
||
private static byte[] addSkPrefix(String skString){ | ||
String skEncoded = "302e020100300506032b657004220420" + skString; | ||
return Utils.hexToBytes(skEncoded); | ||
} | ||
|
||
private static byte[] computeA0Address(byte[] publicKey) { | ||
byte A0_IDENTIFIER = (byte) 0xa0; | ||
ByteBuffer buf = ByteBuffer.allocate(32); | ||
buf.put(A0_IDENTIFIER); | ||
buf.put(blake256(publicKey), 1, 31); | ||
return buf.array(); | ||
} | ||
|
||
private static byte[] blake256(byte[] input) { | ||
Blake2b digest = Blake2b.Digest.newInstance(32); | ||
digest.update(input); | ||
return digest.digest(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package main; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import java.math.BigInteger; | ||
|
||
public class VerifierTest { | ||
@Test | ||
public void testMatchedSignerRegular() throws Exception{ | ||
PrivateKey random = PrivateKey.random(); | ||
byte[] signed = getSignedTransaction(random); | ||
Assert.assertTrue(SignedTransactionVerifier.isSignerForRegularTransaction(signed, random.getPublicAionAddress())); | ||
|
||
} | ||
|
||
@Test | ||
public void testUnMatchedSignerRegular() throws Exception{ | ||
PrivateKey expectedSigner = PrivateKey.random(); | ||
PrivateKey otherSigner = PrivateKey.random(); | ||
byte[] signed = getSignedTransaction(expectedSigner); | ||
Assert.assertFalse(SignedTransactionVerifier.isSignerForRegularTransaction(signed, otherSigner.copyOfUnderlyingBytes())); | ||
|
||
} | ||
|
||
@Test | ||
public void testMatchedSignerInvokable() throws Exception{ | ||
PrivateKey random = PrivateKey.random(); | ||
byte[] signed = getSignedInvokable(random); | ||
Assert.assertTrue(SignedTransactionVerifier.isSignerForInvokableTransaction(signed, random.getPublicAionAddress())); | ||
|
||
} | ||
|
||
@Test | ||
public void testUnMatchedSignerInvokable() throws Exception{ | ||
PrivateKey expectedSigner = PrivateKey.random(); | ||
PrivateKey otherSigner = PrivateKey.random(); | ||
byte[] signed = getSignedInvokable(expectedSigner); | ||
Assert.assertFalse(SignedTransactionVerifier.isSignerForInvokableTransaction(signed, otherSigner.copyOfUnderlyingBytes())); | ||
|
||
} | ||
|
||
private byte[] getSignedInvokable(PrivateKey privateKey) throws Exception { | ||
return new SignedInvokableTransactionBuilder().privateKey(privateKey.copyOfUnderlyingBytes()) | ||
.executor(PrivateKey.random().getPublicAionAddress()) | ||
.data(new byte[32]) | ||
.destination(PrivateKey.random().getPublicAionAddress()) | ||
.senderNonce(BigInteger.ZERO) | ||
.buildSignedInvokableTransaction(); | ||
} | ||
|
||
private byte[] getSignedTransaction(PrivateKey privateKey) throws Exception { | ||
return new SignedTransactionBuilder().privateKey(privateKey.copyOfUnderlyingBytes()) | ||
.data(new byte[0]) | ||
.energyLimit(200000) | ||
.energyPrice(10000000000L) | ||
.senderNonce(BigInteger.ZERO) | ||
.buildSignedTransaction(); | ||
} | ||
} |