Browse Source

Merge branch 'feature/crypto-spi' into feature/optimize-tx-tree

tags/1.0.0
huanghaiquan 5 years ago
parent
commit
170e49c995
44 changed files with 3391 additions and 1386 deletions
  1. +0
    -19
      source/crypto/crypto-adv/pom.xml
  2. +68
    -46
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java
  3. +0
    -98
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java
  4. +0
    -165
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java
  5. +51
    -0
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java
  6. +101
    -0
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java
  7. +59
    -0
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java
  8. +197
    -40
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java
  9. +0
    -75
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java
  10. +0
    -129
      source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java
  11. +13
    -19
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java
  12. +16
    -21
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java
  13. +55
    -72
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java
  14. +0
    -58
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java
  15. +0
    -90
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java
  16. +0
    -43
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java
  17. +0
    -44
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java
  18. +0
    -57
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java
  19. +0
    -113
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java
  20. +202
    -0
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java
  21. +0
    -124
      source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java
  22. +4
    -3
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java
  23. +107
    -16
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java
  24. +5
    -27
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java
  25. +2
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java
  26. +142
    -24
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java
  27. +2
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java
  28. +170
    -0
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java
  29. +10
    -8
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java
  30. +25
    -0
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RIPEMD160Utils.java
  31. +513
    -2
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java
  32. +352
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java
  33. +488
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java
  34. +100
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java
  35. +78
    -2
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java
  36. +72
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java
  37. +32
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java
  38. +426
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java
  39. +1
    -1
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java
  40. +5
    -13
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java
  41. +25
    -4
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java
  42. +0
    -1
      source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java
  43. +42
    -70
      source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java
  44. +28
    -0
      source/utils/utils-common/src/test/java/test/my/utils/security/RSAUtilsTest.java

+ 0
- 19
source/crypto/crypto-adv/pom.xml View File

@@ -27,20 +27,6 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>net.i2p.crypto</groupId>
<artifactId>eddsa</artifactId>
@@ -52,11 +38,6 @@
<version>5.1.0</version>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-framework</artifactId>


+ 68
- 46
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/mpc/MultiSum.java View File

@@ -2,85 +2,89 @@ package com.jd.blockchain.crypto.mpc;

import java.math.BigInteger;

import com.jd.blockchain.crypto.paillier.PaillierPublicKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import com.jd.blockchain.crypto.paillier.PublicKey;
import com.jd.blockchain.crypto.utils.sm.SM2Utils;
import com.jd.blockchain.crypto.utils.sm.SM3Utils;
import com.jd.blockchain.utils.io.BytesUtils;

public class MultiSum {

private ECPrivateKeyParameters ePrivKey;
private ECPublicKeyParameters ePubKey;
private ECCurve curve;
private ECDomainParameters domainParams;
private static byte[] ePrivKey;
private static byte[] ePubKey;
private static ECCurve curve;
private static ECDomainParameters domainParams;

public void generateEphemeralKeyPair(){
public static void generateEphemeralKeyPair(){
AsymmetricCipherKeyPair eKeyPair = SM2Utils.generateKeyPair();
this.ePrivKey = (ECPrivateKeyParameters) eKeyPair.getPrivate();
this.ePubKey = (ECPublicKeyParameters) eKeyPair.getPublic();
this.curve = SM2Utils.getCurve();
this.domainParams = SM2Utils.getDomainParams();

ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters) eKeyPair.getPrivate();
ECPublicKeyParameters ecPubKey= (ECPublicKeyParameters) eKeyPair.getPublic();
ePrivKey = bigIntegerToBytes(ecPrivKey.getD());
ePubKey = ecPubKey.getQ().getEncoded(false);
curve = SM2Utils.getCurve();
domainParams = SM2Utils.getDomainParams();
}

public BigInteger calculateAgreement(CipherParameters otherEPubKey){
public static byte[] calculateAgreement(byte[] otherEPubKey, byte[] ePrivKey){
ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
basicAgreement.init(ePrivKey);
return basicAgreement.calculateAgreement(otherEPubKey);
ECPoint ePubKeyPoint = resolvePubKeyBytes(otherEPubKey);
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(ePubKeyPoint, domainParams);
ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(new BigInteger(1,ePrivKey), domainParams);

basicAgreement.init(privateKey);
BigInteger agreement = basicAgreement.calculateAgreement(pubKey);
return bigIntegerToBytes(agreement);
}

public static BigInteger deriveShares(byte[] frontID, byte[] rearID, BigInteger agreement){
byte[] agreementBytes = agreement.toByteArray();
public static byte[] deriveShares(byte[] frontID, byte[] rearID, byte[] agreementBytes){
byte[] inputBytes = BytesUtils.concat(frontID,rearID,agreementBytes);
return new BigInteger(1,SM3Utils.hash(inputBytes));
return SM3Utils.hash(inputBytes);
}

public static BigInteger encryptBlindedMsg(PublicKey encKey, BigInteger msg, BigInteger frontShare, BigInteger rearShare){
return encKey.encrypt(msg.add(frontShare).subtract(rearShare).mod(encKey.getN()));
public static byte[] encryptBlindedMsg(byte[] paillierPubKey, int input, byte[] frontShare, byte[] rearShare){
BigInteger integer = BigInteger.valueOf(input);
BigInteger frontInteger = new BigInteger(1,frontShare);
BigInteger rearInteger = new BigInteger(1,rearShare);
PaillierPublicKeyParameters encKey = PaillierUtils.bytes2PubKey(paillierPubKey);
BigInteger modulus = encKey.getModulus();
BigInteger plaintext = integer.add(frontInteger).subtract(rearInteger).mod(modulus);
return PaillierUtils.encrypt(plaintext.toByteArray(),encKey);
}

public static BigInteger aggregateCiphertexts(PublicKey encKey, BigInteger... bigIntegersList){
BigInteger aggregatedCiphertext = BigInteger.ONE;
for (BigInteger entry : bigIntegersList) {
aggregatedCiphertext = aggregatedCiphertext.multiply(entry).mod(encKey.getnSquared());
}
return aggregatedCiphertext;
public static byte[] aggregateCiphertexts(byte[] paillierPubKey, byte[]... ciphertexts){
return PaillierUtils.add(paillierPubKey,ciphertexts);
}

public static BigInteger decrypt(KeyPair keyPair, BigInteger ciphertext){
return keyPair.decrypt(ciphertext);
public static byte[] decrypt(byte[] paillierPrivKey, byte[] ciphertext){
return PaillierUtils.decrypt(ciphertext,paillierPrivKey);
}

public ECPublicKeyParameters getEPubKey(){return ePubKey;}

public ECPrivateKeyParameters getEPrivKey(){return ePrivKey;}
public static byte[] getEPubKey(){return ePubKey;}

public static byte[] getEPrivKey(){return ePrivKey;}

public byte[] getEPubKeyBytes(){
byte[] ePubKeyBytes = new byte[65];
byte[] ePubKeyBytesX = ePubKey.getQ().getAffineXCoord().getEncoded();
byte[] ePubKeyBytesY = ePubKey.getQ().getAffineYCoord().getEncoded();
System.arraycopy(Hex.decode("04"),0,ePubKeyBytes,0,1);
System.arraycopy(ePubKeyBytesX,0,ePubKeyBytes,1,32);
System.arraycopy(ePubKeyBytesY,0,ePubKeyBytes,1+32,32);
return ePubKeyBytes;
}

public byte[] getEPrivKeyBytes(){
return PaillierUtils.BigIntegerToLBytes(ePrivKey.getD(),32);
}
// public byte[] getEPubKeyBytes(){
// byte[] ePubKeyBytes = new byte[65];
// byte[] ePubKeyBytesX = ePubKey.getQ().getAffineXCoord().getEncoded();
// byte[] ePubKeyBytesY = ePubKey.getQ().getAffineYCoord().getEncoded();
// System.arraycopy(Hex.decode("04"),0,ePubKeyBytes,0,1);
// System.arraycopy(ePubKeyBytesX,0,ePubKeyBytes,1,32);
// System.arraycopy(ePubKeyBytesY,0,ePubKeyBytes,1+32,32);
// return ePubKeyBytes;
// }
//
// public byte[] getEPrivKeyBytes(){
// return bigIntegerToBytes(ePrivKey.getD());
// }

public ECPublicKeyParameters resolveEPubKey(byte[] ePubKeyBytes){
byte[] ePubKeyX = new byte[32];
@@ -95,4 +99,22 @@ public class MultiSum {
return new ECPrivateKeyParameters(new BigInteger(1,ePrivKeyBytes),domainParams);
}

// To convert BigInteger to byte[] whose length is l
private static byte[] bigIntegerToBytes(BigInteger b){
byte[] tmp = b.toByteArray();
byte[] result = new byte[32];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
else {
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length);
}
return result;
}

// To retrieve the public key point from publicKey in byte array mode
private static ECPoint resolvePubKeyBytes(byte[] publicKey){
return curve.decodePoint(publicKey);
}

}

+ 0
- 98
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPair.java View File

@@ -1,98 +0,0 @@
package com.jd.blockchain.crypto.paillier;

import java.math.BigInteger;
import java.util.List;

import com.jd.blockchain.utils.io.BytesUtils;

/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/**
* A class that holds a pair of associated public and private keys.
*/
public class KeyPair {
private final PrivateKey privateKey;
private final PublicKey publicKey;
private final BigInteger upperBound;

public KeyPair(PrivateKey privateKey, PublicKey publicKey, BigInteger upperBound) {
this.privateKey = privateKey;
this.publicKey = publicKey;
this.upperBound = upperBound;
}

public KeyPair(byte[] privKeyBytes,byte[] pubKeyBytes,byte[] upperBoundBytes){
this.privateKey = new PrivateKey(privKeyBytes);
this.publicKey = new PublicKey(pubKeyBytes);
this.upperBound = new BigInteger(upperBoundBytes);
}

public KeyPair(byte[] keyPairBytes){
List<byte[]> list = PaillierUtils.split(keyPairBytes, "##KeyPair##".getBytes());
this.privateKey = new PrivateKey(list.get(0));
this.publicKey = new PublicKey(list.get(1));
this.upperBound = new BigInteger(list.get(2));
}

public PrivateKey getPrivateKey() {
return privateKey;
}

public PublicKey getPublicKey() {
return publicKey;
}

public BigInteger getUpperBound() { return upperBound; }

/**
* Decrypts the given ciphertext.
*
* @param c The ciphertext that should be decrypted.
* @return The corresponding plaintext. If an upper bound was given to {@link KeyPairBuilder},
* the result can also be negative. See {@link KeyPairBuilder#upperBound(BigInteger)} for details.
*/
public final BigInteger decrypt(BigInteger c) {

BigInteger n = publicKey.getN();
BigInteger nSquare = publicKey.getnSquared();
BigInteger lambda = privateKey.getLambda();

BigInteger u = privateKey.getPreCalculatedDenominator();

BigInteger p = c.modPow(lambda, nSquare).subtract(BigInteger.ONE).divide(n).multiply(u).mod(n);

if (upperBound != null && p.compareTo(upperBound) > 0) {
p = p.subtract(n);
}

return p;
}

public byte[] getUpperBoundBytes(){ return upperBound.toByteArray(); }

public byte[] getKeyPairBytes(){
return BytesUtils.concat(privateKey.getPrivKeyBytes(),"##KeyPair##".getBytes(),publicKey.getPubKeyBytes(),"##KeyPair##".getBytes(),upperBound.toByteArray());
}
}

+ 0
- 165
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/KeyPairBuilder.java View File

@@ -1,165 +0,0 @@
package com.jd.blockchain.crypto.paillier;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/**
* A class that is used for generating a pair of associated public and private
* keys.
*
* @see KeyPair
*/
public class KeyPairBuilder {

private int bits = 1024;

private int certainty = 0;

private Random rng;

private BigInteger upperBound;

/**
* Sets the size of the key to be created.
* <p>
* The default size is 1024 bits.
*
* @param bits The size of the key in bits.
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder bits(int bits) {
this.bits = bits;
return this;
}

/**
* See {@link BigInteger#BigInteger(int, int, Random)} for more details.
* <p>
* The default value is 0.
*
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder certainty(int certainty) {
this.certainty = certainty;
return this;
}

/**
* Sets the random number generator that is used for the generation of
* internally needed prime numbers.
* <p>
* The default is {@link SecureRandom}.
* <p>
* <b>Warning:</b>
* The change of this value affects the security of the whole cryptographic
* system.
*
* @param rng The random number generator that should be used instead of
* {@link SecureRandom}.
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder randomNumberGenerator(Random rng) {
this.rng = rng;
return this;
}

/**
* Sets an upper bound that is used for decrypting ciphertexts representing a negative value.
* <p>
* In most cases the upper bound should be the same as of the underlying number system -
* for example {@link Integer#MAX_VALUE}.
*
* @param b The upper bound.
* @return This instance of KeyPairBuilder for method chaining.
*/
public KeyPairBuilder upperBound(BigInteger b) {
this.upperBound = b;
return this;
}

/**
* Creates a pair of associated public and private keys.
*
* @return The pair of associated public and private keys.
*/
public KeyPair generateKeyPair() {
if (rng == null) {
rng = new SecureRandom();
}

BigInteger p, q;
int length = bits / 2;
if (certainty > 0) {
p = new BigInteger(length, certainty, rng);
q = new BigInteger(length, certainty, rng);
} else {
p = BigInteger.probablePrime(length, rng);
q = BigInteger.probablePrime(length, rng);
}

BigInteger n = p.multiply(q);
BigInteger nSquared = n.multiply(n);

BigInteger pMinusOne = p.subtract(BigInteger.ONE);
BigInteger qMinusOne = q.subtract(BigInteger.ONE);

BigInteger lambda = this.lcm(pMinusOne, qMinusOne);

BigInteger g;
BigInteger helper;

do {
g = new BigInteger(bits, rng);
helper = calculateL(g.modPow(lambda, nSquared), n);

} while (!helper.gcd(n).equals(BigInteger.ONE));

PublicKey publicKey = new PublicKey(n, nSquared, g, bits);
PrivateKey privateKey = new PrivateKey(lambda, helper.modInverse(n));

return new KeyPair(privateKey, publicKey, upperBound);

}

// TODO separate this somewhere
private BigInteger calculateL(BigInteger u, BigInteger n) {
BigInteger result = u.subtract(BigInteger.ONE);
result = result.divide(n);
return result;
}

// TODO add to own BigInteger extended class
private BigInteger lcm(BigInteger a, BigInteger b) {
BigInteger result;
BigInteger gcd = a.gcd(b);

result = a.abs().divide(gcd);
result = result.multiply(b.abs());

return result;
}
}

+ 51
- 0
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierKeyPairGenerator.java View File

@@ -0,0 +1,51 @@
package com.jd.blockchain.crypto.paillier;

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.math.Primes;
import org.bouncycastle.util.BigIntegers;

import java.math.BigInteger;
import java.security.SecureRandom;

/**
* @author zhanglin33
* @title: PaillierKeyPairGenerator
* @description: generator of paillier key pair
* @date 2019-04-30, 14:48
*/
public class PaillierKeyPairGenerator {

private static final int STRENGTH = 2048;

public AsymmetricCipherKeyPair generateKeyPair() {

int pLength = (STRENGTH + 1) / 2;
int qLength = STRENGTH - pLength;

BigInteger p;
BigInteger q;
BigInteger n;

do {
do {
SecureRandom pRandom = new SecureRandom();
p = BigIntegers.createRandomPrime(pLength, 1, pRandom);
} while (!isProbablePrime(p));
do {
SecureRandom qRandom = new SecureRandom();
q = BigIntegers.createRandomPrime(qLength, 1, qRandom);
} while (q.equals(p) || !isProbablePrime(p));
n = q.multiply(p);
} while (n.bitLength() != STRENGTH);

return new AsymmetricCipherKeyPair(new PaillierPublicKeyParameters(n), new PaillierPrivateKeyParameters(p,q));
}

// Primes class for FIPS 186-4 C.3 primality checking
private boolean isProbablePrime(BigInteger x)
{
int iterations = 3;
SecureRandom random = new SecureRandom();
return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, random, iterations);
}
}

+ 101
- 0
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPrivateKeyParameters.java View File

@@ -0,0 +1,101 @@
package com.jd.blockchain.crypto.paillier;

import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

import java.math.BigInteger;

import static org.bouncycastle.util.BigIntegers.ONE;

/**
* @author zhanglin33
* @title: PaillierPrivateKeyParameters
* @description: parameters about Paillier private key
* @date 2019-04-30, 14:39
*/
public class PaillierPrivateKeyParameters extends AsymmetricKeyParameter {

private BigInteger p;

private BigInteger q;

private BigInteger pSquared;

private BigInteger qSquared;

private BigInteger pInverse;

private BigInteger muP;

private BigInteger muQ;

public PaillierPrivateKeyParameters(BigInteger p, BigInteger q) {
super(true);
BigInteger generator = p.multiply(q).add(ONE);
this.p = p;
this.pSquared = p.multiply(p);
this.q = q;
this.qSquared = q.multiply(q);
this.pInverse = p.modInverse(q);
this.muP = hFunction(generator, p, pSquared);
this.muQ = hFunction(generator, q, qSquared);
}

public PaillierPrivateKeyParameters(BigInteger p, BigInteger pSquared, BigInteger q, BigInteger qSquared,
BigInteger pInverse, BigInteger muP, BigInteger muQ){
super(true);
this.p = p;
this.pSquared = pSquared;
this.q = q;
this.qSquared = qSquared;
this.pInverse = pInverse;
this.muP = muP;
this.muQ = muQ;
}


// mu = h(x) = (L(g^(x-1) mod x^2))^(-1) mod n
private BigInteger hFunction(BigInteger generator, BigInteger x, BigInteger xSquared) {
BigInteger phiX = lFunction(generator.modPow(x.subtract(ONE),xSquared),x);
return phiX.modInverse(x);
}

// L(x) = (x-1) / n
public BigInteger lFunction(BigInteger x, BigInteger n) {
return x.subtract(ONE).divide(n);
}

public BigInteger getP()
{
return p;
}

public BigInteger getPSquared()
{
return pSquared;
}

public BigInteger getQ()
{
return q;
}

public BigInteger getQSquared()
{
return qSquared;
}

public BigInteger getPInverse()
{
return pInverse;
}

public BigInteger getMuP()
{
return muP;
}

public BigInteger getMuQ()
{
return muQ;
}
}

+ 59
- 0
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierPublicKeyParameters.java View File

@@ -0,0 +1,59 @@
package com.jd.blockchain.crypto.paillier;

import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

import java.math.BigInteger;

import static org.bouncycastle.util.BigIntegers.ONE;

/**
* @author zhanglin33
* @title: PaillierPublicKeyParameters
* @description: parameters about Paillier public key
* @date 2019-04-30, 14:41
*/
public class PaillierPublicKeyParameters extends AsymmetricKeyParameter {

private BigInteger modulus;
private BigInteger modulusSquared;
private BigInteger generator;

public PaillierPublicKeyParameters(BigInteger modulus) {
super(false);
this.modulus = validate(modulus);
this.modulusSquared = modulus.multiply(modulus);
this.generator = modulus.add(ONE);
}

public BigInteger getModulus() {
return modulus;
}

public BigInteger getModulusSquared() {
return modulusSquared;
}

public BigInteger getGenerator() {
return generator;
}

private BigInteger validate(BigInteger modulus)
{
if ((modulus.intValue() & 1) == 0)
{
throw new IllegalArgumentException("The modulus is even!");
}

// the value is the product of the 132 smallest primes from 3 to 751
if (!modulus.gcd(new BigInteger("145188775577763990151158743208307020242261438098488931355057091965" +
"931517706595657435907891265414916764399268423699130577757433083166" +
"651158914570105971074227669275788291575622090199821297575654322355" +
"049043101306108213104080801056529374892690144291505781966373045481" +
"8359472391642885328171302299245556663073719855")).equals(ONE))
{
throw new IllegalArgumentException("The modulus has a small prime factor!");
}

return modulus;
}
}

+ 197
- 40
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PaillierUtils.java View File

@@ -1,16 +1,200 @@
package com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.utils.io.BytesUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.security.SecureRandom;
import static org.bouncycastle.util.BigIntegers.ONE;

/**
* @author zhanglin33
* @title: PaillierUtils
* @description: encryption, decryption, homomorphic addition and scalar multiplication in Paillier algorithm
* @date 2019-04-30, 14:49
*/
public class PaillierUtils {

// To convert BigInteger to byte[] whose length is l
public static byte[] BigIntegerToLBytes(BigInteger b, int l){
private static final int MODULUS_LENGTH = 256;
private static final int MODULUSSQUARED_LENGTH = 512;

private static final int P_LENGTH = 128;
private static final int PSQUARED_LENGTH = 256;
private static final int Q_LENGTH = 128;
private static final int QSQUARED_LENGTH = 256;
private static final int PINVERSE_LENGTH = 128;
private static final int MUP_LENGTH = 128;
private static final int MUQ_LENGTH = 128;

private static final int PRIVKEY_LENGTH = P_LENGTH + PSQUARED_LENGTH + Q_LENGTH + QSQUARED_LENGTH
+ PINVERSE_LENGTH + MUP_LENGTH + MUQ_LENGTH;

public static AsymmetricCipherKeyPair generateKeyPair(){
PaillierKeyPairGenerator generator = new PaillierKeyPairGenerator();
return generator.generateKeyPair();
}

public static byte[] encrypt(byte[] plainBytes, byte[] publicKey) {
PaillierPublicKeyParameters pubKeyParams = bytes2PubKey(publicKey);
return encrypt(plainBytes, pubKeyParams);
}

public static byte[] encrypt(byte[] plainBytes, PaillierPublicKeyParameters pubKeyParams) {
SecureRandom random = new SecureRandom();
return encrypt(plainBytes, pubKeyParams, random);
}

// c = g^m * r^n mod n^2 = (1+n)^m * r^n mod n^2 = (1 + n*m mod n^2) * r^n mod n^2
public static byte[] encrypt(byte[] plainBytes, PaillierPublicKeyParameters pubKeyParams, SecureRandom random){

BigInteger n = pubKeyParams.getModulus();
BigInteger nSquared = pubKeyParams.getModulusSquared();

BigInteger m = new BigInteger(1,plainBytes);
BigInteger r = new BigInteger(n.bitLength(), random);

BigInteger rawCiphertext = n.multiply(m).add(ONE).mod(nSquared);
BigInteger c = r.modPow(n, nSquared).multiply(rawCiphertext).mod(nSquared);

return bigIntegerToBytes(c, MODULUSSQUARED_LENGTH);
}


public static byte[] decrypt(byte[] cipherBytes, byte[] privateKey) {
PaillierPrivateKeyParameters privKeyParams = bytes2PrivKey(privateKey);
return decrypt(cipherBytes,privKeyParams);
}
// m mod p = L(c^(p-1) mod p^2) * muP mod p
// m mod q = L(c^(q-1) mod q^2) * muQ mod q
// m = (m mod p) * (1/q mod p) * q + (m mod q) * (1/p mod q) * p
// = ((m mod q)-(m mod p)) * (1/p mod q) mod q * p + (m mod p)
public static byte[] decrypt(byte[] cipherBytes, PaillierPrivateKeyParameters privKeyParams){

BigInteger cihphertext = new BigInteger(1, cipherBytes);

BigInteger p = privKeyParams.getP();
BigInteger pSquared = privKeyParams.getPSquared();
BigInteger q = privKeyParams.getQ();
BigInteger qSquared = privKeyParams.getQSquared();
BigInteger pInverse = privKeyParams.getPInverse();
BigInteger muP = privKeyParams.getMuP();
BigInteger muQ = privKeyParams.getMuQ();

BigInteger mModP =
privKeyParams.lFunction(cihphertext.modPow(p.subtract(ONE),pSquared),p).multiply(muP).mod(p);
BigInteger mModQ =
privKeyParams.lFunction(cihphertext.modPow(q.subtract(ONE),qSquared),q).multiply(muQ).mod(q);

BigInteger midValue = mModQ.subtract(mModP).multiply(pInverse).mod(q);
BigInteger m = midValue.multiply(p).add(mModP);

return m.toByteArray();
}


public static byte[] pubKey2Bytes(PaillierPublicKeyParameters pubKeyParams) {
BigInteger n = pubKeyParams.getModulus();
return bigIntegerToBytes(n, MODULUS_LENGTH);
}

public static PaillierPublicKeyParameters bytes2PubKey(byte[] publicKey) {

if (publicKey.length != MODULUS_LENGTH) {
throw new IllegalArgumentException("publicKey's length does not meet algorithm's requirement!");
}

BigInteger n = new BigInteger(1, publicKey);
return new PaillierPublicKeyParameters(n);
}


public static byte[] privKey2Bytes(PaillierPrivateKeyParameters privKeyParams) {

BigInteger p = privKeyParams.getP();
BigInteger pSquared = privKeyParams.getPSquared();
BigInteger q = privKeyParams.getQ();
BigInteger qSquared = privKeyParams.getQSquared();
BigInteger pInverse = privKeyParams.getPInverse();
BigInteger muP = privKeyParams.getMuP();
BigInteger muQ = privKeyParams.getMuQ();

byte[] pBytes = bigIntegerToBytes(p, P_LENGTH);
byte[] pSquaredBytes = bigIntegerToBytes(pSquared, PSQUARED_LENGTH);
byte[] qBytes = bigIntegerToBytes(q, Q_LENGTH);
byte[] qSquaredBytes = bigIntegerToBytes(qSquared, QSQUARED_LENGTH);
byte[] pInverseBytes = bigIntegerToBytes(pInverse, PINVERSE_LENGTH);
byte[] muPBytes = bigIntegerToBytes(muP, MUP_LENGTH);
byte[] muQBytes = bigIntegerToBytes(muQ, MUQ_LENGTH);

return BytesUtils.concat(pBytes,pSquaredBytes,qBytes,qSquaredBytes,pInverseBytes,muPBytes,muQBytes);
}

public static PaillierPrivateKeyParameters bytes2PrivKey(byte[] privateKey) {

if (privateKey.length != PRIVKEY_LENGTH) {
throw new IllegalArgumentException("privateKey's length does not meet algorithm's requirement!");
}

byte[] pBytes = new byte[P_LENGTH];
byte[] pSquaredBytes = new byte[PSQUARED_LENGTH];
byte[] qBytes = new byte[Q_LENGTH];
byte[] qSquaredBytes = new byte[QSQUARED_LENGTH];
byte[] pInverseBytes = new byte[PINVERSE_LENGTH];
byte[] muPBytes = new byte[MUP_LENGTH];
byte[] muQBytes = new byte[MUQ_LENGTH];

split(privateKey,pBytes,pSquaredBytes,qBytes,qSquaredBytes,pInverseBytes,muPBytes,muQBytes);

BigInteger p = new BigInteger(1, pBytes);
BigInteger pSquared = new BigInteger(1, pSquaredBytes);
BigInteger q = new BigInteger(1, qBytes);
BigInteger qSquared = new BigInteger(1, qSquaredBytes);
BigInteger pInverse = new BigInteger(1, pInverseBytes);
BigInteger muP = new BigInteger(1, muPBytes);
BigInteger muQ = new BigInteger(1, muQBytes);

return new PaillierPrivateKeyParameters(p,pSquared,q,qSquared,pInverse,muP,muQ);
}

public static byte[] add(byte[] publicKey, byte[]... ciphertexts) {
PaillierPublicKeyParameters pubKeyParams = bytes2PubKey(publicKey);
return add(pubKeyParams,ciphertexts);
}

public static byte[] add(PaillierPublicKeyParameters pubKeyParams, byte[]... ciphertexts) {

BigInteger result = ONE;
BigInteger multiplier;
BigInteger nSquared = pubKeyParams.getModulusSquared();
for (byte[] each: ciphertexts) {
multiplier = new BigInteger(1, each);
result = result.multiply(multiplier).mod(nSquared);
}

return bigIntegerToBytes(result, MODULUSSQUARED_LENGTH);
}

public static byte[] scalarMultiply(byte[] publicKey, byte[] cipherBytes, long scalar) {
PaillierPublicKeyParameters pubKeyParams = bytes2PubKey(publicKey);
return scalarMultiply(pubKeyParams,cipherBytes,scalar);
}

public static byte[] scalarMultiply(PaillierPublicKeyParameters pubKeyParams, byte[] cipherBytes, long scalar) {

BigInteger nSquared = pubKeyParams.getModulusSquared();
BigInteger cihertext = new BigInteger(1, cipherBytes);
BigInteger exponent = BigInteger.valueOf(scalar);

BigInteger result = cihertext.modPow(exponent,nSquared);

return bigIntegerToBytes(result, MODULUSSQUARED_LENGTH);
}

// To convert BigInteger to byte array in specified size
private static byte[] bigIntegerToBytes(BigInteger b, int bytesSize){
byte[] tmp = b.toByteArray();
byte[] result = new byte[l];
byte[] result = new byte[bytesSize];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
@@ -20,42 +204,15 @@ public class PaillierUtils {
return result;
}

public static byte[] intToBytes(int i){
byte[] result = new byte[4];
result[0] = (byte) (i >> 24);
result[1] = (byte) (i >> 16);
result[2] = (byte) (i >> 8);
result[3] = (byte) (i);
return result;
}

public static int bytesToInt(byte[] array){
int result = 0;
result |= ((array[0] & 0xFF) << 24);
result |= ((array[1] & 0xFF) << 16);
result |= ((array[2] & 0xFF) << 8);
result |= ((array[3] & 0xFF));
return result;
}
private static void split(byte[] src, byte[]... bytesList) {

public static List<byte[]> split(byte[] array, byte[] delimiter) {
List<byte[]> byteArrays = new LinkedList<>();
if (delimiter.length == 0) {
return byteArrays;
}
int begin = 0;

outer:
for (int i = 0; i < array.length - delimiter.length + 1; i++) {
for (int j = 0; j < delimiter.length; j++) {
if (array[i + j] != delimiter[j]) {
continue outer;
}
int srcPos = 0;
for (byte[] each: bytesList){
System.arraycopy(src,srcPos,each,0,each.length);
srcPos += each.length;
if (srcPos >= src.length){
break;
}
byteArrays.add(Arrays.copyOfRange(array, begin, i));
begin = i + delimiter.length;
}
byteArrays.add(Arrays.copyOfRange(array, begin, array.length));
return byteArrays;
}
}

+ 0
- 75
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PrivateKey.java View File

@@ -1,75 +0,0 @@
package com.jd.blockchain.crypto.paillier;

import java.math.BigInteger;
import java.util.List;
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

import com.jd.blockchain.utils.io.BytesUtils;

/**
* A class that represents the private part of the Paillier key pair.
*/
public class PrivateKey {

private final BigInteger lambda;
private final BigInteger preCalculatedDenominator;

public PrivateKey(BigInteger lambda, BigInteger preCalculatedDenominator) {
this.lambda = lambda;

this.preCalculatedDenominator = preCalculatedDenominator;
}

public PrivateKey(byte[] lambdaBytes, byte[] preCalculatedDenominatorBytes){
this.lambda = new BigInteger(lambdaBytes);
this.preCalculatedDenominator = new BigInteger(preCalculatedDenominatorBytes);
}

public PrivateKey(byte[] privKeyBytes){
List<byte[]> list = PaillierUtils.split(privKeyBytes, "##PrivateKey##".getBytes());
this.lambda = new BigInteger(list.get(0));
this.preCalculatedDenominator = new BigInteger(list.get(1));
}

public BigInteger getLambda() {
return lambda;
}

public BigInteger getPreCalculatedDenominator() {
return preCalculatedDenominator;
}

public byte[] getLambdaBytes(){
return lambda.toByteArray();
}

public byte[] getPreCalculatedDenominatorBytes(){
return preCalculatedDenominator.toByteArray();
}

public byte[] getPrivKeyBytes(){
return BytesUtils.concat(getLambdaBytes(),"##PrivateKey##".getBytes(),getPreCalculatedDenominatorBytes());
}
}

+ 0
- 129
source/crypto/crypto-adv/src/main/java/com/jd/blockchain/crypto/paillier/PublicKey.java View File

@@ -1,129 +0,0 @@
package com.jd.blockchain.crypto.paillier;

import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Hendrik Kunert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

import com.jd.blockchain.utils.io.ByteArray;
import com.jd.blockchain.utils.io.BytesUtils;

/**
* A class that represents the public part of the Paillier key pair.
* <p>
* As in all asymmetric cryptographic systems it is responsible for the
* encryption.
* <p>
* Additional instructions for the decryption can be found on {@link KeyPair}.
*
* @see KeyPair
*/
public class PublicKey {
private final int bits;
private final BigInteger n;
private final BigInteger nSquared;
private final BigInteger g;

public PublicKey(BigInteger n, BigInteger nSquared, BigInteger g, int bits) {
this.n = n;
this.nSquared = nSquared;
this.bits = bits;
this.g = g;
}

public PublicKey(byte[] nBytes, byte[] nSquaredBytes, byte[] gBytes, byte[] bitsBytes) {
this.n = new BigInteger(nBytes);
this.nSquared = new BigInteger(nSquaredBytes);
this.g = new BigInteger(gBytes);
this.bits = PaillierUtils.bytesToInt(bitsBytes);
}

public PublicKey(byte[] pubKeyBytes){
List<byte[]> list = PaillierUtils.split(pubKeyBytes, "##PublicKey##".getBytes());
this.n = new BigInteger(list.get(0));
this.nSquared = new BigInteger(list.get(1));
this.g = new BigInteger(list.get(2));
this.bits = PaillierUtils.bytesToInt(list.get(3));
}


public int getBits() {
return bits;
}

public BigInteger getN() {
return n;
}

public BigInteger getnSquared() {
return nSquared;
}

public BigInteger getG() {
return g;
}

/**
* Encrypts the given plaintext.
*
* @param m The plaintext that should be encrypted.
* @return The corresponding ciphertext.
*/
public final BigInteger encrypt(BigInteger m) {

BigInteger r;
do {
r = new BigInteger(bits, new Random());
} while (r.compareTo(n) >= 0);

BigInteger result = g.modPow(m, nSquared);
BigInteger x = r.modPow(n, nSquared);

result = result.multiply(x);
result = result.mod(nSquared);

return result;
}

public byte[] getBitsBytes(){
return PaillierUtils.intToBytes(bits);
}

public byte[] getNBytes(){ return n.toByteArray(); }

public byte[] getNSquaredBytes(){
return nSquared.toByteArray();
}

public byte[] getGBytes(){
return g.toByteArray();
}

public byte[] getPubKeyBytes(){
return BytesUtils.concat(getNBytes(),"##PublicKey##".getBytes(),getNSquaredBytes(),"##PublicKey##".getBytes(),getGBytes(),"##PublicKey##".getBytes(),getBitsBytes());
}
}


+ 13
- 19
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/EqualVerifyTest.java View File

@@ -39,35 +39,29 @@ public class EqualVerifyTest {
byte[] responderOutput;
boolean isEqual;

int i;

for (i = 0; i < 1000; i++) {
sponsorInput = 666;
responderInput = 666;

sponsorInput = 666;
responderInput = 666;

sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
responderEPubKeyBytes,responderEPrivKeyBytes);

isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);
isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);

assertTrue(isEqual);
}
assertTrue(isEqual);

for (i = 0; i < 1000; i++){

sponsorInput = 666;
responderInput = 667;
sponsorInput = 666;
responderInput = 667;

sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
sponsorOutput = EqualVerify.sponsor(sponsorInput,sponsorEPubKeyBytes);
responderOutput = EqualVerify.responder(responderInput,sponsorOutput,
responderEPubKeyBytes,responderEPrivKeyBytes);

isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);
isEqual = EqualVerify.sponsorCheck(sponsorInput,responderOutput,sponsorEPrivKeyBytes);

assertTrue(!isEqual);
}
}
assertTrue(!isEqual);

}
}

+ 16
- 21
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/IntCompareTest.java View File

@@ -25,26 +25,21 @@ public class IntCompareTest {
byte[][] cipherArray;
byte[][] aggregatedCipherArray;
int output;
int i;

for (i = 0; i < 1000; i++) {
int sponsorInput = 10000;
int responderInput = 9999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(1, output);
}

for (i = 0; i < 1000; i++) {
int sponsorInput = 10000;
int responderInput = 19999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(0, output);
}

int sponsorInput = 10000;
int responderInput = 9999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(1, output);

sponsorInput = 10000;
responderInput = 19999;

cipherArray = IntCompare.sponsor(sponsorInput, pubKeyBytes);
aggregatedCipherArray = IntCompare.responder(responderInput, cipherArray, pubKeyBytes);
output = IntCompare.sponsorOutput(aggregatedCipherArray, privKeyBytes);
assertEquals(0, output);
}
}

+ 55
- 72
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/mpc/MultiSumTest.java View File

@@ -1,105 +1,88 @@
package test.com.jd.blockchain.crypto.mpc;

import com.jd.blockchain.crypto.mpc.MultiSum;
import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Before;
import com.jd.blockchain.crypto.paillier.PaillierPrivateKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierPublicKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.*;

public class MultiSumTest {

private KeyPair keyPair;
private PublicKey encKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
keyPair = keygen.generateKeyPair();
encKey = keyPair.getPublicKey();
}
@Test
public void testMultiSum() {

MultiSum instance1 = new MultiSum();
MultiSum instance2 = new MultiSum();
MultiSum instance3 = new MultiSum();
AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

BigInteger value1 = BigInteger.valueOf(6);
BigInteger value2 = BigInteger.valueOf(60);
BigInteger value3 = BigInteger.valueOf(600);
BigInteger expectedSum = BigInteger.valueOf(666);
byte[] encKey = PaillierUtils.pubKey2Bytes(pubKeyParams);
byte[] decKey = PaillierUtils.privKey2Bytes(privKeyParams);

int int1 = 6;
int int2 = 60;
int int3 = 600;
int sum = 666;

byte[] id1 = "1".getBytes();
byte[] id2 = "2".getBytes();
byte[] id3 = "3".getBytes();

instance1.generateEphemeralKeyPair();
instance2.generateEphemeralKeyPair();
instance3.generateEphemeralKeyPair();
MultiSum.generateEphemeralKeyPair();
byte[] ePubKey1 = MultiSum.getEPubKey();
byte[] ePrivKey1 = MultiSum.getEPrivKey();

ECPublicKeyParameters ePubKey1 = instance1.getEPubKey();
ECPublicKeyParameters ePubKey2 = instance2.getEPubKey();
ECPublicKeyParameters ePubKey3 = instance3.getEPubKey();
MultiSum.generateEphemeralKeyPair();
byte[] ePubKey2 = MultiSum.getEPubKey();
byte[] ePrivKey2 = MultiSum.getEPrivKey();

BigInteger sk12 = instance1.calculateAgreement(ePubKey2);
BigInteger sk23 = instance2.calculateAgreement(ePubKey3);
BigInteger sk31 = instance1.calculateAgreement(ePubKey3);
MultiSum.generateEphemeralKeyPair();
byte[] ePubKey3 = MultiSum.getEPubKey();
byte[] ePrivKey3 = MultiSum.getEPrivKey();

assertEquals(sk12,instance2.calculateAgreement(ePubKey1));
assertEquals(sk23,instance3.calculateAgreement(ePubKey2));
assertEquals(sk31,instance3.calculateAgreement(ePubKey1));

BigInteger s12 = MultiSum.deriveShares(id1,id2,sk12);
BigInteger s23 = MultiSum.deriveShares(id2,id3,sk23);
BigInteger s31 = MultiSum.deriveShares(id3,id1,sk31);
byte[] sk12 = MultiSum.calculateAgreement(ePubKey2,ePrivKey1);
byte[] sk23 = MultiSum.calculateAgreement(ePubKey3,ePrivKey2);
byte[] sk31 = MultiSum.calculateAgreement(ePubKey1,ePrivKey3);

assertEquals(s12, MultiSum.deriveShares(id1,id2,sk12));
assertEquals(s23, MultiSum.deriveShares(id2,id3,sk23));
assertEquals(s31, MultiSum.deriveShares(id3,id1,sk31));
assertArrayEquals(sk12,MultiSum.calculateAgreement(ePubKey1,ePrivKey2));
assertArrayEquals(sk23,MultiSum.calculateAgreement(ePubKey2,ePrivKey3));
assertArrayEquals(sk31,MultiSum.calculateAgreement(ePubKey3,ePrivKey1));

BigInteger c1 = MultiSum.encryptBlindedMsg(encKey,value1,s12,s31);
BigInteger c2 = MultiSum.encryptBlindedMsg(encKey,value2,s23,s12);
BigInteger c3 = MultiSum.encryptBlindedMsg(encKey,value3,s31,s23);
byte[] s12 = MultiSum.deriveShares(id1,id2,sk12);
byte[] s23 = MultiSum.deriveShares(id2,id3,sk23);
byte[] s31 = MultiSum.deriveShares(id3,id1,sk31);

BigInteger aggregatedCiphertext = MultiSum.aggregateCiphertexts(encKey,c1,c2,c3);
assertArrayEquals(s12, MultiSum.deriveShares(id1,id2,sk12));
assertArrayEquals(s23, MultiSum.deriveShares(id2,id3,sk23));
assertArrayEquals(s31, MultiSum.deriveShares(id3,id1,sk31));

BigInteger decryptedValue = MultiSum.decrypt(keyPair,aggregatedCiphertext);
byte[] c1 = MultiSum.encryptBlindedMsg(encKey,int1,s12,s31);
byte[] c2 = MultiSum.encryptBlindedMsg(encKey,int2,s23,s12);
byte[] c3 = MultiSum.encryptBlindedMsg(encKey,int3,s31,s23);

assertEquals(expectedSum,decryptedValue);
}
byte[] aggregatedCiphertext = MultiSum.aggregateCiphertexts(encKey,c1,c2,c3);

@Test
public void testResolveEPrivKey(){
byte[] decryptedValue = MultiSum.decrypt(decKey,aggregatedCiphertext);

MultiSum instance = new MultiSum();
instance.generateEphemeralKeyPair();

ECPrivateKeyParameters expectedEPrivKey = instance.getEPrivKey();
byte[] ePrivKeyBytes = instance.getEPrivKeyBytes();
ECPrivateKeyParameters ePrivKey = instance.resolveEPrivKey(ePrivKeyBytes);
assertEquals(expectedEPrivKey.getD(),ePrivKey.getD());
assertEquals(sum,byteArrayToInt(decryptedValue));
}

@Test
public void testResolveEPubKey(){

MultiSum instance = new MultiSum();
instance.generateEphemeralKeyPair();

ECPublicKeyParameters expectedEPubKey = instance.getEPubKey();
byte[] ePubKeyBytes = instance.getEPubKeyBytes();
ECPublicKeyParameters ePubKey = instance.resolveEPubKey(ePubKeyBytes);

assertEquals(Hex.toHexString(expectedEPubKey.getQ().getAffineXCoord().getEncoded()),Hex.toHexString(ePubKey.getQ().getAffineXCoord().getEncoded()));
assertEquals(Hex.toHexString(expectedEPubKey.getQ().getAffineYCoord().getEncoded()),Hex.toHexString(ePubKey.getQ().getAffineYCoord().getEncoded()));
private static int byteArrayToInt(byte[] input) {
int result;
int length = input.length;
byte[] buffer = new byte[4];
if (length <= buffer.length){
System.arraycopy(input,0,buffer,buffer.length - length,length);
} else {
System.arraycopy(input,length - buffer.length,buffer,0, buffer.length);
}
result = buffer[3] & 0xFF |
(buffer[2] & 0xFF) << 8 |
(buffer[1] & 0xFF) << 16 |
(buffer[0] & 0xFF) << 24;
return result;
}
}

+ 0
- 58
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/DecryptionTest.java View File

@@ -1,58 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;

import static org.junit.Assert.assertEquals;

/**
* Created by kunerd on 22.09.15.
*/
@RunWith(value = Parameterized.class)
public class DecryptionTest {

@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(createTestParameter(Long.MIN_VALUE),
createTestParameter(Integer.MIN_VALUE),
createTestParameter(Short.MIN_VALUE),
createTestParameter(0),
createTestParameter(Short.MAX_VALUE),
createTestParameter(Integer.MAX_VALUE),
createTestParameter(Long.MAX_VALUE));
}

private BigInteger input;
private BigInteger expected;

public DecryptionTest(BigInteger input, BigInteger expected) {
this.input = input;
this.expected = expected;
}

@Test
public void test() {
KeyPair keyPair = new KeyPairBuilder().upperBound(BigInteger.valueOf(Long.MAX_VALUE))
.generateKeyPair();
PublicKey publicKey = keyPair.getPublicKey();

BigInteger encryptedData = publicKey.encrypt(input);

assertEquals(expected, keyPair.decrypt(encryptedData));
}

private static Object[] createTestParameter(long plaintext) {
BigInteger p = BigInteger.valueOf(plaintext);
return new Object[]{p, p};
}

}


+ 0
- 90
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/HomomorphicPropertiesTest.java View File

@@ -1,90 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class HomomorphicPropertiesTest {
private KeyPair keypair;
private PublicKey publicKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
this.keypair = keygen.generateKeyPair();
this.publicKey = keypair.getPublicKey();
}

@Test
public void testHomomorphicAddition() {
BigInteger plainA = BigInteger.valueOf(102);
BigInteger plainB = BigInteger.valueOf(203);

BigInteger encryptedA = publicKey.encrypt(plainA);
BigInteger encryptedB = publicKey.encrypt(plainB);

BigInteger decryptedProduct = keypair.decrypt(encryptedA.multiply(
encryptedB).mod(publicKey.getnSquared()));
BigInteger plainSum = plainA.add(plainB).mod(publicKey.getN());

assertEquals(decryptedProduct, plainSum);
}

@Test
public void testHomomorphicConstantMultiplication() {
BigInteger plainA = BigInteger.valueOf(14);
BigInteger plainB = BigInteger.valueOf(203);

BigInteger encryptedA = publicKey.encrypt(plainA);

BigInteger decryptedPow = keypair.decrypt(encryptedA.modPow(plainB,
publicKey.getnSquared()));
BigInteger plainSum = plainA.multiply(plainB).mod(publicKey.getN());

assertEquals(decryptedPow, plainSum);
}

@Test
public void testHomomorphicMultiplication() {
BigInteger plainA = BigInteger.valueOf(23);
BigInteger plainB = BigInteger.valueOf(234);

BigInteger encryptedA = publicKey.encrypt(plainA);
BigInteger decryptedPowA = keypair.decrypt(encryptedA.modPow(
plainB, publicKey.getnSquared()));
BigInteger plainSumA = plainA.multiply(plainB).mod(publicKey.getN());

assertEquals(decryptedPowA, plainSumA);

BigInteger encryptedB = publicKey.encrypt(plainB);
BigInteger decryptedPowB = keypair.decrypt(encryptedB.modPow(
plainA, publicKey.getnSquared()));
BigInteger plainSumB = plainA.multiply(plainB).mod(publicKey.getN());

assertEquals(decryptedPowB, plainSumB);

assertEquals(decryptedPowA, decryptedPowB);
}

@Test
public void testHomomorphicMultiplicationPowG() {
BigInteger plainA = BigInteger.valueOf(230);
BigInteger plainB = BigInteger.valueOf(100);

BigInteger g = publicKey.getG();

BigInteger encryptedA = publicKey.encrypt(plainA);
BigInteger decryptedPow = keypair.decrypt(encryptedA.multiply(g.modPow(
plainB, publicKey.getnSquared()).mod(publicKey.getnSquared())));

BigInteger plainSumA = plainA.add(plainB).mod(publicKey.getN());

assertEquals(decryptedPow, plainSumA);
}
}

+ 0
- 43
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/JPaillierTest.java View File

@@ -1,43 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

public class JPaillierTest {
private KeyPair keyPair;
private PublicKey publicKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
keyPair = keygen.generateKeyPair();
publicKey = keyPair.getPublicKey();
}

@Test
public void testEncryption() {
BigInteger plainData = BigInteger.valueOf(10);

BigInteger encryptedData = publicKey.encrypt(plainData);

assertNotEquals(plainData, encryptedData);
}

@Test
public void testDecyption() {
BigInteger plainData = BigInteger.valueOf(10);

BigInteger encryptedData = publicKey.encrypt(plainData);
BigInteger decryptedData = keyPair.decrypt(encryptedData);

assertEquals(plainData, decryptedData);
}
}

+ 0
- 44
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPrivateKeyTest.java View File

@@ -1,44 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PrivateKey;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class KeyPairBuilderPrivateKeyTest {
private KeyPairBuilder keygen;
private KeyPair keypair;
private PrivateKey privateKey;

@Before
public void init() {
this.keygen = new KeyPairBuilder();
this.keypair = keygen.generateKeyPair();
this.privateKey = keypair.getPrivateKey();
}

@Test
public void testPreCalculatedDenominator() {
PublicKey publicKey = keypair.getPublicKey();

BigInteger preCalculatedDenominator = privateKey.getPreCalculatedDenominator();

BigInteger g = publicKey.getG();
BigInteger n = publicKey.getN();
BigInteger nSquared = publicKey.getnSquared();
BigInteger lambda = privateKey.getLambda();

BigInteger expected = g.modPow(lambda, nSquared);
expected = expected.subtract(BigInteger.ONE);
expected = expected.divide(n);
expected = expected.modInverse(n);

assertEquals(expected, preCalculatedDenominator);
}
}

+ 0
- 57
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderPublicKeyTest.java View File

@@ -1,57 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PrivateKey;
import com.jd.blockchain.crypto.paillier.PublicKey;
import org.junit.Before;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class KeyPairBuilderPublicKeyTest {

private KeyPair keypair;
private PublicKey publicKey;

@Before
public void init() {
KeyPairBuilder keygen = new KeyPairBuilder();
this.keypair = keygen.generateKeyPair();
this.publicKey = keypair.getPublicKey();
}

@Test
public void testBitsSetup() {
int BITS = 1024;
assertEquals(BITS, publicKey.getBits());
}

@Test
public void testCalculationOfNSquared() {

BigInteger n = publicKey.getN();
BigInteger nSquared = n.multiply(n);

assertEquals(nSquared, publicKey.getnSquared());
}

@Test
public void testCalculationOfGOfG() {
PrivateKey privateKey = keypair.getPrivateKey();

BigInteger n = publicKey.getN();
BigInteger nSquared = publicKey.getnSquared();
BigInteger g = publicKey.getG();
BigInteger lambda = privateKey.getLambda();

BigInteger l = g.modPow(lambda, nSquared);
l = l.subtract(BigInteger.ONE);
l = l.divide(n);

assertEquals(BigInteger.ONE, l.gcd(n));
}

}

+ 0
- 113
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/KeyPairBuilderTest.java View File

@@ -1,113 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import static org.junit.Assert.assertEquals;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.jd.blockchain.crypto.paillier.KeyPair;
import com.jd.blockchain.crypto.paillier.KeyPairBuilder;
import com.jd.blockchain.crypto.paillier.PrivateKey;
import com.jd.blockchain.crypto.paillier.PublicKey;

@RunWith(PowerMockRunner.class)
@PrepareForTest(KeyPairBuilder.class)
public class KeyPairBuilderTest {

private static final int BITS = 128;

private KeyPairBuilder keygen;
private PublicKey publicKey;
private PrivateKey privateKey;

private BigInteger p = BigInteger.valueOf(5);
private BigInteger q = BigInteger.valueOf(7);
private BigInteger g1 = BigInteger.valueOf(35);
private BigInteger g2 = BigInteger.valueOf(36);

private Random rng;

@Before
public void beforeEach() {
rng = PowerMockito.mock(SecureRandom.class);

keygen = new KeyPairBuilder()
.bits(BITS)
.randomNumberGenerator(rng);

PowerMockito.mockStatic(BigInteger.class);
}

private void prepareTest() throws Exception {

PowerMockito.when(BigInteger.probablePrime(BITS / 2, rng)).thenReturn(p, q);

PowerMockito.whenNew(BigInteger.class).withArguments(BITS, rng).thenReturn(g1, g2);

KeyPair keypair = keygen.generateKeyPair();

publicKey = keypair.getPublicKey();
privateKey = keypair.getPrivateKey();
}

@Test
public void computationOfN() throws Exception {
prepareTest();

BigInteger e = p.multiply(q);
BigInteger a = publicKey.getN();

assertEquals(e, a);
}


@Test
public void computationOfLambda() throws Exception {
BigInteger e = new BigInteger("12");

prepareTest();

BigInteger a = privateKey.getLambda();

assertEquals(e, a);
}

@Test
public void computationOfG() throws Exception {
prepareTest();

PowerMockito.verifyNew(BigInteger.class, Mockito.times(2)).withArguments(Mockito.eq(128), Mockito.any(Random.class));
}

@Test
public void withoutCertainty() throws Exception {
prepareTest();

PowerMockito.verifyStatic(Mockito.times(2));
BigInteger.probablePrime(BITS / 2, rng);

}

@Test
public void withCertainty() throws Exception {
int certainty = 6;

keygen.certainty(certainty);

PowerMockito.whenNew(BigInteger.class).withArguments(BITS / 2, certainty, rng).thenReturn(p, q);

prepareTest();

PowerMockito.verifyNew(BigInteger.class, Mockito.times(2)).withArguments(BITS / 2, certainty, rng);
}

}

+ 202
- 0
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java View File

@@ -0,0 +1,202 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.PaillierPrivateKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierPublicKeyParameters;
import com.jd.blockchain.crypto.paillier.PaillierUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.junit.Test;

import java.math.BigInteger;
import java.security.SecureRandom;

import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: PaillierUtilsTest
* @description: Tests on PaillierUtils
* @date 2019-04-30, 14:54
*/
public class PaillierUtilsTest {
@Test
public void generateKeyPairTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

BigInteger n = pubKeyParams.getModulus();
BigInteger nSquared = pubKeyParams.getModulusSquared();
BigInteger g = pubKeyParams.getGenerator();

BigInteger nConverted = new BigInteger(1, bigIntegerToBytes(n,256));
BigInteger nSquaredConverted = new BigInteger(1, bigIntegerToBytes(nSquared,512));
BigInteger gConverted = new BigInteger(1, bigIntegerToBytes(g,256));
assertEquals(nConverted, n);
assertEquals(nSquaredConverted, nSquared);
assertEquals(gConverted, g);

BigInteger p = privKeyParams.getP();
BigInteger pSquared = privKeyParams.getPSquared();
BigInteger q = privKeyParams.getQ();
BigInteger qSquared = privKeyParams.getQSquared();
BigInteger pInverse = privKeyParams.getPInverse();
BigInteger muP = privKeyParams.getMuP();
BigInteger muQ = privKeyParams.getMuQ();

BigInteger pConverted = new BigInteger(1, bigIntegerToBytes(p,128));
BigInteger pSquaredConverted = new BigInteger(1, bigIntegerToBytes(pSquared,256));
BigInteger qConverted = new BigInteger(1, bigIntegerToBytes(q,128));
BigInteger qSquaredConverted = new BigInteger(1, bigIntegerToBytes(qSquared,256));
BigInteger pInverseConverted = new BigInteger(1, bigIntegerToBytes(pInverse,128));
BigInteger muPConverted = new BigInteger(1, bigIntegerToBytes(muP,128));
BigInteger muQConverted = new BigInteger(1, bigIntegerToBytes(muQ,128));
assertEquals(pConverted, p);
assertEquals(pSquaredConverted, pSquared);
assertEquals(qConverted, q);
assertEquals(qSquaredConverted, qSquared);
assertEquals(pInverseConverted, pInverse);
assertEquals(muPConverted, muP);
assertEquals(muQConverted, muQ);
}

@Test
public void encryptTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);

SecureRandom random = new SecureRandom();
byte[] data = new byte[256];
random.nextBytes(data);

byte[] ciphertextFromParams = PaillierUtils.encrypt(data,pubKeyParams);
byte[] ciphertextFromBytes = PaillierUtils.encrypt(data,pubKeyBytes);

assertEquals(512,ciphertextFromParams.length);
assertEquals(512,ciphertextFromBytes.length);
}

@Test
public void decryptTest(){

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);
byte[] privKeyBytes = PaillierUtils.privKey2Bytes(privKeyParams);

int input = 666;
byte[] data = intToByteArray(input);

byte[] ciphertextFromParams = PaillierUtils.encrypt(data,pubKeyParams);
byte[] ciphertextFromBytes = PaillierUtils.encrypt(data,pubKeyBytes);

byte[] plaintextFromParams = PaillierUtils.decrypt(ciphertextFromBytes,privKeyParams);
byte[] plaintextFromBytes = PaillierUtils.decrypt(ciphertextFromParams,privKeyBytes);

int outputFromParams = byteArrayToInt(plaintextFromParams);
int outputFromBytes = byteArrayToInt(plaintextFromBytes);

assertEquals(input,outputFromParams);
assertEquals(input,outputFromBytes);
}

@Test
public void addTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);

int input1 = 600;
int input2 = 60;
int input3 = 6;

int sum = 666;

byte[] data1 = intToByteArray(input1);
byte[] data2 = intToByteArray(input2);
byte[] data3 = intToByteArray(input3);

byte[] ciphertext1 = PaillierUtils.encrypt(data1,pubKeyParams);
byte[] ciphertext2 = PaillierUtils.encrypt(data2,pubKeyParams);
byte[] ciphertext3 = PaillierUtils.encrypt(data3,pubKeyParams);

byte[] aggregatedCiphertext = PaillierUtils.add(pubKeyParams,ciphertext1,ciphertext2,ciphertext3);
byte[] plaintext = PaillierUtils.decrypt(aggregatedCiphertext,privKeyParams);

int output = byteArrayToInt(plaintext);
assertEquals(sum,output);

aggregatedCiphertext = PaillierUtils.add(pubKeyBytes,ciphertext1,ciphertext2,ciphertext3);
plaintext = PaillierUtils.decrypt(aggregatedCiphertext,privKeyParams);

output = byteArrayToInt(plaintext);
assertEquals(sum,output);
}

@Test
public void scalarMultiplyTest() {

AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair();
PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic();
PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams);

int input = 111;
int scalar = 6;
byte[] data = intToByteArray(input);

byte[] ciphertext = PaillierUtils.encrypt(data,pubKeyParams);
byte[] ciphertextPowered = PaillierUtils.scalarMultiply(pubKeyBytes,ciphertext,scalar);
byte[] plaintextMultiplied = PaillierUtils.decrypt(ciphertextPowered,privKeyParams);

int output = byteArrayToInt(plaintextMultiplied);
assertEquals(input * scalar, output);
}

private static byte[] intToByteArray(int input) {
byte[] result = new byte[4];
result[0] = (byte) ((input >> 24) & 0xFF);
result[1] = (byte) ((input >> 16) & 0xFF);
result[2] = (byte) ((input >> 8 ) & 0xFF);
result[3] = (byte) ((input ) & 0xFF);
return result;
}

private static int byteArrayToInt(byte[] input) {
int result;
int length = input.length;
byte[] buffer = new byte[4];
if (length <= buffer.length){
System.arraycopy(input,0,buffer,buffer.length - length,length);
} else {
System.arraycopy(input,length - buffer.length,buffer,0, buffer.length);
}
result = buffer[3] & 0xFF |
(buffer[2] & 0xFF) << 8 |
(buffer[1] & 0xFF) << 16 |
(buffer[0] & 0xFF) << 24;
return result;
}

// To convert BigInteger to byte array in specified size
private static byte[] bigIntegerToBytes(BigInteger b, int bytesSize){
byte[] tmp = b.toByteArray();
byte[] result = new byte[bytesSize];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
else {
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length);
}
return result;
}
}

+ 0
- 124
source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/ResolveTest.java View File

@@ -1,124 +0,0 @@
package test.com.jd.blockchain.crypto.paillier;

import com.jd.blockchain.crypto.paillier.*;
import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class ResolveTest {

@Test
public void testResolvePrivateKey() {
KeyPairBuilder keygen = new KeyPairBuilder();
KeyPair keyPair = keygen.generateKeyPair();

PrivateKey privKey = keyPair.getPrivateKey();
BigInteger lambda = privKey.getLambda();
BigInteger preCalculatedDenominator = privKey.getPreCalculatedDenominator();

byte[] privKeyBytes = privKey.getPrivKeyBytes();
byte[] lambdaBytes = privKey.getLambdaBytes();
byte[] preCalculatedDenominatorBytes = privKey.getPreCalculatedDenominatorBytes();

assertEquals(lambda,new BigInteger(lambdaBytes));
assertEquals(preCalculatedDenominator,new BigInteger(preCalculatedDenominatorBytes));

assertEquals(lambda,new PrivateKey(lambda,preCalculatedDenominator).getLambda());
assertEquals(preCalculatedDenominator,(new PrivateKey(lambda,preCalculatedDenominator)).getPreCalculatedDenominator());

assertEquals(lambda,(new PrivateKey(lambdaBytes,preCalculatedDenominatorBytes)).getLambda());
assertEquals(preCalculatedDenominator,(new PrivateKey(lambdaBytes,preCalculatedDenominatorBytes)).getPreCalculatedDenominator());

assertEquals(lambda,(new PrivateKey(privKeyBytes)).getLambda());
assertEquals(preCalculatedDenominator,(new PrivateKey(privKeyBytes)).getPreCalculatedDenominator());
}

@Test
public void testResolvePublicKey() {
KeyPairBuilder keygen = new KeyPairBuilder();
KeyPair keyPair = keygen.generateKeyPair();

PublicKey pubKey = keyPair.getPublicKey();
int bits = pubKey.getBits();
BigInteger n = pubKey.getN();
BigInteger nSquared = pubKey.getnSquared();
BigInteger g = pubKey.getG();

byte[] pubKeyBytes = pubKey.getPubKeyBytes();
byte[] bitsBytes = pubKey.getBitsBytes();
byte[] nBytes = pubKey.getNBytes();
byte[] nSquaredBytes = pubKey.getNSquaredBytes();
byte[] gBytes = pubKey.getGBytes();

assertEquals(bits,PaillierUtils.bytesToInt(bitsBytes));
assertEquals(n,new BigInteger(nBytes));
assertEquals(nSquared,new BigInteger(nSquaredBytes));
assertEquals(g,new BigInteger(gBytes));

assertEquals(bits,(new PublicKey(n,nSquared,g,bits)).getBits());
assertEquals(n,(new PublicKey(n,nSquared,g,bits)).getN());
assertEquals(nSquared,(new PublicKey(n,nSquared,g,bits)).getnSquared());
assertEquals(g,(new PublicKey(n,nSquared,g,bits)).getG());

assertEquals(bits,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getBits());
assertEquals(n,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getN());
assertEquals(nSquared,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getnSquared());
assertEquals(g,(new PublicKey(nBytes,nSquaredBytes,gBytes,bitsBytes)).getG());

assertEquals(bits,(new PublicKey(pubKeyBytes)).getBits());
assertEquals(n,(new PublicKey(pubKeyBytes)).getN());
assertEquals(nSquared,(new PublicKey(pubKeyBytes)).getnSquared());
assertEquals(g,(new PublicKey(pubKeyBytes)).getG());
}

@Test
public void testResolveKeyPair() {
KeyPairBuilder keygen = new KeyPairBuilder();
keygen.upperBound(new BigInteger(PaillierUtils.intToBytes(Integer.MAX_VALUE)));
KeyPair keyPair = keygen.generateKeyPair();

PrivateKey privKey = keyPair.getPrivateKey();
PublicKey pubKey = keyPair.getPublicKey();
BigInteger upperBound = keyPair.getUpperBound();

byte[] keyPairBytes = keyPair.getKeyPairBytes();
byte[] privKeyBytes = privKey.getPrivKeyBytes();
byte[] pubKeyBytes = pubKey.getPubKeyBytes();
byte[] upperBoundBytes = keyPair.getUpperBoundBytes();

assertEquals(upperBound,keyPair.getUpperBound());
assertEquals(privKey.getLambda(),keyPair.getPrivateKey().getLambda());
assertEquals(privKey.getPreCalculatedDenominator(),keyPair.getPrivateKey().getPreCalculatedDenominator());
assertEquals(pubKey.getBits(),keyPair.getPublicKey().getBits());
assertEquals(pubKey.getN(),keyPair.getPublicKey().getN());
assertEquals(pubKey.getnSquared(),keyPair.getPublicKey().getnSquared());
assertEquals(pubKey.getG(),keyPair.getPublicKey().getG());

assertEquals(upperBound,(new KeyPair(privKey,pubKey,upperBound).getUpperBound()));
assertEquals(privKey.getLambda(),(new KeyPair(privKey,pubKey,upperBound).getPrivateKey().getLambda()));
assertEquals(privKey.getPreCalculatedDenominator(),(new KeyPair(privKey,pubKey,upperBound).getPrivateKey().getPreCalculatedDenominator()));
assertEquals(pubKey.getBits(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getBits()));
assertEquals(pubKey.getN(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getN()));
assertEquals(pubKey.getnSquared(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getnSquared()));
assertEquals(pubKey.getG(),(new KeyPair(privKey,pubKey,upperBound).getPublicKey().getG()));

assertEquals(upperBound,(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getUpperBound()));
assertEquals(privKey.getLambda(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPrivateKey().getLambda()));
assertEquals(privKey.getPreCalculatedDenominator(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPrivateKey().getPreCalculatedDenominator()));
assertEquals(pubKey.getBits(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getBits()));
assertEquals(pubKey.getN(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getN()));
assertEquals(pubKey.getnSquared(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getnSquared()));
assertEquals(pubKey.getG(),(new KeyPair(privKeyBytes,pubKeyBytes,upperBoundBytes).getPublicKey().getG()));

assertEquals(upperBound,(new KeyPair(keyPairBytes).getUpperBound()));
assertEquals(privKey.getLambda(),(new KeyPair(keyPairBytes).getPrivateKey().getLambda()));
assertEquals(privKey.getPreCalculatedDenominator(),(new KeyPair(keyPairBytes).getPrivateKey().getPreCalculatedDenominator()));
assertEquals(pubKey.getBits(),(new KeyPair(keyPairBytes).getPublicKey().getBits()));
assertEquals(pubKey.getN(),(new KeyPair(keyPairBytes).getPublicKey().getN()));
assertEquals(pubKey.getnSquared(),(new KeyPair(keyPairBytes).getPublicKey().getnSquared()));
assertEquals(pubKey.getG(),(new KeyPair(keyPairBytes).getPublicKey().getG()));

}
}

+ 4
- 3
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java View File

@@ -23,13 +23,14 @@ public class ClassicCryptoService implements CryptoService {

public static final JVMSecureRandomFunction JVM_SECURE_RANDOM = new JVMSecureRandomFunction();

// public static final ECDSASignatureFunction ECDSA = new
// ECDSASignatureFunction();
public static final ECDSASignatureFunction ECDSA = new ECDSASignatureFunction();

public static final RSACryptoFunction RSA = new RSACryptoFunction();

private static final Collection<CryptoFunction> FUNCTIONS;

static {
List<CryptoFunction> funcs = Arrays.asList(AES, ED25519, RIPEMD160, SHA256, JVM_SECURE_RANDOM);
List<CryptoFunction> funcs = Arrays.asList(AES, ED25519, ECDSA, RSA, RIPEMD160, SHA256, JVM_SECURE_RANDOM);
FUNCTIONS = Collections.unmodifiableList(funcs);
}



+ 107
- 16
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java View File

@@ -1,60 +1,129 @@
package com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.utils.classic.ECDSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;

import java.math.BigInteger;

import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES;
import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;

public class ECDSASignatureFunction implements SignatureFunction {

private static final CryptoAlgorithm ECDSA = ClassicAlgorithm.ECDSA;

private static final int PUBKEY_SIZE = 65;
private static final int PRIVKEY_SIZE = 32;
private static final int SIGNATUREDIGEST_SIZE = 64;

private static final int PUBKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PUBKEY_SIZE;
private static final int PRIVKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PRIVKEY_SIZE;
private static final int SIGNATUREDIGEST_LENGTH = ALGORYTHM_CODE_SIZE + SIGNATUREDIGEST_SIZE;

ECDSASignatureFunction() {
}

@Override
public SignatureDigest sign(PrivKey privKey, byte[] data) {
return null;

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

// 验证原始私钥长度为256比特,即32字节
if (rawPrivKeyBytes.length != PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应ECDSA签名算法
if (privKey.getAlgorithm() != ECDSA.code()) {
throw new CryptoException("This key is not ECDSA private key!");
}

// 调用ECDSA签名算法计算签名结果
return new SignatureDigest(ECDSA, ECDSAUtils.sign(data, rawPrivKeyBytes));
}

@Override
public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) {
return false;

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawDigestBytes = digest.getRawDigest();

// 验证原始公钥长度为256比特,即32字节
if (rawPubKeyBytes.length != PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应ECDSA签名算法
if (pubKey.getAlgorithm() != ECDSA.code()) {
throw new CryptoException("This key is not ECDSA public key!");
}

// 验证签名数据的算法标识对应ECDSA签名算法,并且原始摘要长度为64字节
if (digest.getAlgorithm() != ECDSA.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not ECDSA signature digest!");
}

// 调用ECDSA验签算法验证签名结果
return ECDSAUtils.verify(data, rawPubKeyBytes, rawDigestBytes);
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {
return null;
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawPubKeyBytes = ECDSAUtils.retrievePublicKey(rawPrivKeyBytes);
return new PubKey(ECDSA, rawPubKeyBytes);
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ECDSA签名算法,并且密钥类型是私钥
return privKeyBytes.length == PRIVKEY_LENGTH && CryptoAlgorithm.match(ECDSA, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

@Override
public PrivKey resolvePrivKey(byte[] privKeyBytes) {
return null;
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes are invalid!");
}
}

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ECDSA签名算法,并且密钥类型是公钥
return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(ECDSA, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

@Override
public PubKey resolvePubKey(byte[] pubKeyBytes) {
return null;
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@Override
public boolean supportDigest(byte[] digestBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+摘要长度,字节数组的算法标识对应ECDSA算法
return digestBytes.length == SIGNATUREDIGEST_LENGTH && CryptoAlgorithm.match(ECDSA, digestBytes);
}

@Override
public SignatureDigest resolveDigest(byte[] digestBytes) {
return null;
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes are invalid!");
}
}

@Override
@@ -64,6 +133,28 @@ public class ECDSASignatureFunction implements SignatureFunction {

@Override
public AsymmetricKeypair generateKeypair() {
return null;

// 调用ECDSA算法的密钥生成算法生成公私钥对priKey和pubKey,返回密钥对
AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair();
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate();
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic();

byte[] privKeyBytes = BigIntegerTo32Bytes(privKeyParams.getD());
byte[] pubKeyBytes = pubKeyParams.getQ().getEncoded(false);

return new AsymmetricKeypair(new PubKey(ECDSA, pubKeyBytes), new PrivKey(ECDSA, privKeyBytes));
}

// To convert BigInteger to byte[] whose length is 32
private static byte[] BigIntegerTo32Bytes(BigInteger b){
byte[] tmp = b.toByteArray();
byte[] result = new byte[32];
if (tmp.length > result.length) {
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length);
}
else {
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length);
}
return result;
}
}

+ 5
- 27
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java View File

@@ -49,9 +49,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
}

// 调用ED25519签名算法计算签名结果
// return new SignatureDigest(ED25519, Ed25519Utils.sign_512(data, rawPrivKeyBytes));
return new SignatureDigest(ED25519, ED25519Utils.sign(data, rawPrivKeyBytes));

}

@Override
@@ -70,13 +68,12 @@ public class ED25519SignatureFunction implements SignatureFunction {
throw new CryptoException("This key is not ED25519 public key!");
}

// 验证密文数据的算法标识对应ED25519签名算法,并且原始摘要长度为64字节
// 验证签名数据的算法标识对应ED25519签名算法,并且原始摘要长度为64字节
if (digest.getAlgorithm() != ED25519.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not ED25519 signature digest!");
}

// 调用ED25519验签算法验证签名结果
// return Ed25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes);
return ED25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes);
}

@@ -84,21 +81,8 @@ public class ED25519SignatureFunction implements SignatureFunction {
public PubKey retrievePubKey(PrivKey privKey) {
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawPubKeyBytes = ED25519Utils.retrievePublicKey(rawPrivKeyBytes);
// EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
// EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(rawPrivKeyBytes, spec);
// byte[] rawPubKeyBytes = privateKeySpec.getA().toByteArray();
return new PubKey(ED25519, rawPubKeyBytes);
}
//
// @Override
// public byte[] retrievePubKey(byte[] privKeyBytes) {
//
// byte[] rawPrivKeyBytes = resolvePrivKey(privKeyBytes).getRawKeyBytes();
// EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
// EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(rawPrivKeyBytes, spec);
// byte[] rawPubKeyBytes = privateKeySpec.getA().toByteArray();
// return new PubKey(ED25519, rawPubKeyBytes).toBytes();
// }

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
@@ -112,7 +96,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes is invalid!");
throw new CryptoException("privKeyBytes are invalid!");
}
}

@@ -121,7 +105,6 @@ public class ED25519SignatureFunction implements SignatureFunction {
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应ED25519签名算法,并且密钥类型是公钥
return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(ED25519, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;

}

@Override
@@ -129,7 +112,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes is invalid!");
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@@ -144,7 +127,7 @@ public class ED25519SignatureFunction implements SignatureFunction {
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes is invalid!");
throw new CryptoException("digestBytes are invalid!");
}
}

@@ -155,6 +138,7 @@ public class ED25519SignatureFunction implements SignatureFunction {

@Override
public AsymmetricKeypair generateKeypair() {

// 调用ED25519算法的密钥生成算法生成公私钥对priKey和pubKey,返回密钥对
AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair();
Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate();
@@ -162,12 +146,6 @@ public class ED25519SignatureFunction implements SignatureFunction {

byte[] privKeyBytes = privKeyParams.getEncoded();
byte[] pubKeyBytes = pubKeyParams.getEncoded();
// KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
// KeyPair keyPair = keyPairGenerator.generateKeyPair();
// EdDSAPrivateKey privKey = (EdDSAPrivateKey) keyPair.getPrivate();
// EdDSAPublicKey pubKey = (EdDSAPublicKey) keyPair.getPublic();
// return new CryptoKeyPair(new PubKey(ED25519, pubKey.getAbyte()), new PrivKey(ED25519, privKey.getSeed()));
return new AsymmetricKeypair(new PubKey(ED25519, pubKeyBytes), new PrivKey(ED25519, privKeyBytes));

}
}

+ 2
- 1
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java View File

@@ -9,6 +9,7 @@ import com.jd.blockchain.crypto.CryptoBytes;
import com.jd.blockchain.crypto.CryptoException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.crypto.utils.classic.RIPEMD160Utils;
import com.jd.blockchain.utils.security.RipeMD160Utils;

public class RIPEMD160HashFunction implements HashFunction {
@@ -34,7 +35,7 @@ public class RIPEMD160HashFunction implements HashFunction {
throw new CryptoException("data is null!");
}

byte[] digestBytes = RipeMD160Utils.hash(data);
byte[] digestBytes = RIPEMD160Utils.hash(data);
return new HashDigest(RIPEMD160, digestBytes);
}



+ 142
- 24
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java View File

@@ -1,14 +1,15 @@
package com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.AsymmetricCiphertext;
import com.jd.blockchain.crypto.AsymmetricEncryptionFunction;
import com.jd.blockchain.crypto.Ciphertext;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.utils.classic.RSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;

import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES;
import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;

/**
* @author zhanglin33
@@ -17,78 +18,195 @@ import com.jd.blockchain.crypto.SignatureFunction;
* @date 2019-03-25, 17:28
*/
public class RSACryptoFunction implements AsymmetricEncryptionFunction, SignatureFunction {

private static final CryptoAlgorithm RSA = ClassicAlgorithm.RSA;

// modulus.length = 256, publicExponent.length = 1
private static final int PUBKEY_SIZE = 257;
// modulus.length = 256, publicExponent.length = 1, privateExponent.length = 256, p.length = 128, q.length =128,
// dP.length = 128, dQ.length = 128, qInv.length = 128
private static final int PRIVKEY_SIZE = 1153;

private static final int SIGNATUREDIGEST_SIZE = 256;
private static final int CIPHERTEXTBLOCK_SIZE = 256;

private static final int PUBKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PUBKEY_SIZE;
private static final int PRIVKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + PRIVKEY_SIZE;
private static final int SIGNATUREDIGEST_LENGTH = ALGORYTHM_CODE_SIZE + SIGNATUREDIGEST_SIZE;
@Override
public Ciphertext encrypt(PubKey pubKey, byte[] data) {
return null;

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();

// 验证原始公钥长度为257字节
if (rawPubKeyBytes.length != PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA算法
if (pubKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("The is not RSA public key!");
}

// 调用RSA加密算法计算密文
return new AsymmetricCiphertext(RSA, RSAUtils.encrypt(data, rawPubKeyBytes));
}

@Override
public byte[] decrypt(PrivKey privKey, Ciphertext ciphertext) {
return new byte[0];

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawCiphertextBytes = ciphertext.getRawCiphertext();

// 验证原始私钥长度为1153字节
if (rawPrivKeyBytes.length != PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA算法
if (privKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("This key is not RSA private key!");
}

// 验证密文数据的算法标识对应RSA算法,并且密文是分组长度的整数倍
if (ciphertext.getAlgorithm() != RSA.code()
|| rawCiphertextBytes.length % CIPHERTEXTBLOCK_SIZE != 0) {
throw new CryptoException("This is not RSA ciphertext!");
}

// 调用RSA解密算法得到明文结果
return RSAUtils.decrypt(rawCiphertextBytes, rawPrivKeyBytes);
}

@Override
public PubKey retrievePubKey(PrivKey privKey) {
return null;
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
byte[] rawPubKeyBytes = RSAUtils.retrievePublicKey(rawPrivKeyBytes);
return new PubKey(RSA, rawPubKeyBytes);
}

@Override
public SignatureDigest sign(PrivKey privKey, byte[] data) {
return null;

byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();

// 验证原始私钥长度为1153字节
if (rawPrivKeyBytes.length != PRIVKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA签名算法
if (privKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("This key is not RSA private key!");
}

// 调用RSA签名算法计算签名结果
return new SignatureDigest(RSA, RSAUtils.sign(data, rawPrivKeyBytes));
}

@Override
public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) {
return false;

byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawDigestBytes = digest.getRawDigest();

// 验证原始公钥长度为257字节
if (rawPubKeyBytes.length != PUBKEY_SIZE) {
throw new CryptoException("This key has wrong format!");
}

// 验证密钥数据的算法标识对应RSA签名算法
if (pubKey.getAlgorithm() != RSA.code()) {
throw new CryptoException("This key is not RSA public key!");
}

// 验证签名数据的算法标识对应RSA签名算法,并且原始签名长度为256字节
if (digest.getAlgorithm() != RSA.code() || rawDigestBytes.length != SIGNATUREDIGEST_SIZE) {
throw new CryptoException("This is not RSA signature digest!");
}

// 调用RSA验签算法验证签名结果
return RSAUtils.verify(data, rawPubKeyBytes, rawDigestBytes);
}

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应RSA算法,并且密钥类型是私钥
return privKeyBytes.length == PRIVKEY_LENGTH && CryptoAlgorithm.match(RSA, privKeyBytes)
&& privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE;
}

@Override
public PrivKey resolvePrivKey(byte[] privKeyBytes) {
return null;
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes are invalid!");
}
}

@Override
public boolean supportPubKey(byte[] pubKeyBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+密钥类型长度+椭圆曲线点长度,密钥数据的算法标识对应RSA算法,并且密钥类型是公钥
return pubKeyBytes.length == PUBKEY_LENGTH && CryptoAlgorithm.match(RSA, pubKeyBytes)
&& pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE;
}

@Override
public PubKey resolvePubKey(byte[] pubKeyBytes) {
return null;
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@Override
public boolean supportDigest(byte[] digestBytes) {
return false;
// 验证输入字节数组长度=算法标识长度+签名长度,字节数组的算法标识对应RSA算法
return digestBytes.length == SIGNATUREDIGEST_LENGTH && CryptoAlgorithm.match(RSA, digestBytes);
}

@Override
public SignatureDigest resolveDigest(byte[] digestBytes) {
return null;
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes are invalid!");
}
}

@Override
public boolean supportCiphertext(byte[] ciphertextBytes) {
return false;
// 验证输入字节数组长度=密文分组的整数倍,字节数组的算法标识对应RSA算法
return (ciphertextBytes.length % CIPHERTEXTBLOCK_SIZE == ALGORYTHM_CODE_SIZE)
&& CryptoAlgorithm.match(RSA, ciphertextBytes);
}

@Override
public AsymmetricCiphertext resolveCiphertext(byte[] ciphertextBytes) {
return null;
if (supportCiphertext(ciphertextBytes)) {
return new AsymmetricCiphertext(ciphertextBytes);
} else {
throw new CryptoException("ciphertextBytes are invalid!");
}
}

@Override
public CryptoAlgorithm getAlgorithm() {
return null;
return RSA;
}

@Override
public AsymmetricKeypair generateKeypair() {
return null;

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) keyPair.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) keyPair.getPrivate();

byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey(privKey);

return new AsymmetricKeypair(new PubKey(RSA, pubKeyBytes), new PrivKey(RSA, privKeyBytes));
}
}

+ 2
- 1
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java View File

@@ -9,6 +9,7 @@ import com.jd.blockchain.crypto.CryptoBytes;
import com.jd.blockchain.crypto.CryptoException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.crypto.utils.classic.SHA256Utils;
import com.jd.blockchain.utils.security.ShaUtils;

public class SHA256HashFunction implements HashFunction {
@@ -34,7 +35,7 @@ public class SHA256HashFunction implements HashFunction {
throw new CryptoException("data is null!");
}

byte[] digestBytes = ShaUtils.hash_256(data);
byte[] digestBytes = SHA256Utils.hash(data);
return new HashDigest(SHA256, digestBytes);
}



+ 170
- 0
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java View File

@@ -0,0 +1,170 @@
package com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.CryptoException;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

import java.security.SecureRandom;
import java.util.Arrays;

/**
* @author zhanglin33
* @title: AESUtils
* @description: AES128/CBC/PKCS7Padding symmetric encryption algorithm
* @date 2019-04-22, 09:37
*/
public class AESUtils {

// AES128 supports 128-bit(16 bytes) secret key
private static final int KEY_SIZE = 128 / 8;
// One block contains 16 bytes
private static final int BLOCK_SIZE = 16;
// Initial vector's size is 16 bytes
private static final int IV_SIZE = 16;

/**
* key generation
*
* @return secret key
*/
public static byte[] generateKey(){

CipherKeyGenerator keyGenerator = new CipherKeyGenerator();

// To provide secure randomness and key length as input
// to prepare generate private key
keyGenerator.init(new KeyGenerationParameters(new SecureRandom(), KEY_SIZE * 8));

// To generate key
return keyGenerator.generateKey();
}

public static byte[] generateKey(byte[] seed){
byte[] hash = SHA256Utils.hash(seed);
return Arrays.copyOf(hash, KEY_SIZE);
}


/**
* encryption
*
* @param plainBytes plaintext
* @param secretKey symmetric key
* @param iv initial vector
* @return ciphertext
*/
public static byte[] encrypt(byte[] plainBytes, byte[] secretKey, byte[] iv){

// To ensure that plaintext is not null
if (plainBytes == null)
{
throw new CryptoException("plaintext is null!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

if (iv.length != IV_SIZE)
{
throw new CryptoException("iv's length is wrong!");
}

// To get the value padded into input
int padding = 16 - plainBytes.length % BLOCK_SIZE;
// The plaintext with padding value
byte[] plainBytesWithPadding = new byte[plainBytes.length + padding];
System.arraycopy(plainBytes,0,plainBytesWithPadding,0,plainBytes.length);
// The padder adds PKCS7 padding to the input, which makes its length to
// become an integral multiple of 16 bytes
PKCS7Padding padder = new PKCS7Padding();
// To add padding
padder.addPadding(plainBytesWithPadding, plainBytes.length);

CBCBlockCipher encryptor = new CBCBlockCipher(new AESEngine());
// To provide key and initialisation vector as input
encryptor.init(true,new ParametersWithIV(new KeyParameter(secretKey),iv));
byte[] output = new byte[plainBytesWithPadding.length + IV_SIZE];
// To encrypt the input_p in CBC mode
for(int i = 0 ; i < plainBytesWithPadding.length/BLOCK_SIZE; i++) {
encryptor.processBlock(plainBytesWithPadding, i * BLOCK_SIZE, output, (i + 1) * BLOCK_SIZE);
}

// The IV locates on the first block of ciphertext
System.arraycopy(iv,0,output,0,BLOCK_SIZE);
return output;
}

public static byte[] encrypt(byte[] plainBytes, byte[] secretKey){

byte[] iv = new byte[IV_SIZE];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
return encrypt(plainBytes,secretKey,iv);
}

/**
* decryption
*
* @param cipherBytes ciphertext
* @param secretKey symmetric key
* @return plaintext
*/
public static byte[] decrypt(byte[] cipherBytes, byte[] secretKey){

// To ensure that the ciphertext is not null
if (cipherBytes == null)
{
throw new CryptoException("ciphertext is null!");
}

// To ensure that the ciphertext's length is integral multiples of 16 bytes
if (cipherBytes.length % BLOCK_SIZE != 0)
{
throw new CryptoException("ciphertext's length is wrong!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

byte[] iv = new byte[IV_SIZE];
System.arraycopy(cipherBytes,0,iv,0,BLOCK_SIZE);

CBCBlockCipher decryptor = new CBCBlockCipher(new AESEngine());
// To prepare the decryption
decryptor.init(false,new ParametersWithIV(new KeyParameter(secretKey),iv));
byte[] outputWithPadding = new byte[cipherBytes.length-BLOCK_SIZE];
// To decrypt the input in CBC mode
for(int i = 1 ; i < cipherBytes.length/BLOCK_SIZE ; i++) {
decryptor.processBlock(cipherBytes, i * BLOCK_SIZE, outputWithPadding, (i - 1) * BLOCK_SIZE);
}

int p = outputWithPadding[outputWithPadding.length-1];
// To ensure that the padding of output_p is valid
if(p > BLOCK_SIZE || p < 0x01)
{
throw new CryptoException("There no exists such padding!");

}
for(int i = 0 ; i < p ; i++)
{
if(outputWithPadding[outputWithPadding.length - i -1] != p)
{
throw new CryptoException("Padding is invalid!");
}
}

// To remove the padding from output and obtain plaintext
byte[] output = new byte[outputWithPadding.length - p];
System.arraycopy(outputWithPadding, 0, output, 0, output.length);
return output;
}
}

+ 10
- 8
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java View File

@@ -89,10 +89,10 @@ public class ECDSAUtils {
return sign(data,params);
}

public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random, String ID){
public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random){

ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS);
CipherParameters params = new ParametersWithID(new ParametersWithRandom(privKey,random),ID.getBytes());
CipherParameters params = new ParametersWithRandom(privKey,random);

return sign(data,params);
}
@@ -100,16 +100,14 @@ public class ECDSAUtils {
public static byte[] sign(byte[] data, CipherParameters params){

byte[] hashedMsg = SHA256Utils.hash(data);
return sign(params,hashedMsg);
}

public static byte[] sign(CipherParameters params, byte[] hashedMsg){
ECDSASigner signer = new ECDSASigner();
signer.init(true, params);
BigInteger[] signature = signer.generateSignature(hashedMsg);

// // To decode the signature
// ASN1Sequence sig = ASN1Sequence.getInstance(encodedSignature);
// byte[] rBytes = BigIntegerTo32Bytes(ASN1Integer.getInstance(sig.getObjectAt(0)).getValue());
// byte[] sBytes = BigIntegerTo32Bytes(ASN1Integer.getInstance(sig.getObjectAt(1)).getValue());

byte[] rBytes = BigIntegerTo32Bytes(signature[0]);
byte[] sBytes = BigIntegerTo32Bytes(signature[1]);

@@ -120,6 +118,7 @@ public class ECDSAUtils {
return result;
}


/**
* verification
*
@@ -139,6 +138,10 @@ public class ECDSAUtils {
public static boolean verify(byte[] data, CipherParameters params, byte[] signature){

byte[] hashedMsg = SHA256Utils.hash(data);
return verify(params,signature,hashedMsg);
}

public static boolean verify(CipherParameters params, byte[] signature, byte[] hashedMsg){

byte[] rBytes = new byte[R_SIZE];
byte[] sBytes = new byte[S_SIZE];
@@ -153,7 +156,6 @@ public class ECDSAUtils {
return verifier.verifySignature(hashedMsg,r,s);
}


// To convert BigInteger to byte[] whose length is 32
private static byte[] BigIntegerTo32Bytes(BigInteger b){
byte[] tmp = b.toByteArray();


+ 25
- 0
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RIPEMD160Utils.java View File

@@ -0,0 +1,25 @@
package com.jd.blockchain.crypto.utils.classic;

import org.bouncycastle.crypto.digests.RIPEMD160Digest;

/**
* @author zhanglin33
* @title: RIPEMD160Utils
* @description: RIPEMD160 hash algorithm
* @date 2019-04-10, 16:51
*/
public class RIPEMD160Utils {

// The length of RIPEMD160 output is 20 bytes
private static final int RIPEMD160DIGEST_LENGTH = 160 / 8;

public static byte[] hash(byte[] data){

byte[] result = new byte[RIPEMD160DIGEST_LENGTH];
RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest();

ripemd160Digest.update(data,0,data.length);
ripemd160Digest.doFinal(result,0);
return result;
}
}

+ 513
- 2
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java View File

@@ -1,10 +1,521 @@
package com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.utils.io.BytesUtils;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.signers.RSADigestSigner;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import sun.security.rsa.RSAPrivateCrtKeyImpl;

import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
* @author zhanglin33
* @title: RSAUtils
* @description: RSA encryption and signature algorithms
* @description: RSA2048 encryption(RSA/ECB/PKCS1Padding) and signature(SHA256withRSA) algorithms,
* and keys are output in raw, PKCS1v2 and PKCS8 formats
* @date 2019-03-25, 17:20
*/
public class RSAUtils {
public class RSAUtils {

private static final int KEYSIZEBITS = 2048;
private static final int CERTAINTY = 100;

private static final int MODULUS_LENGTH = 2048 / 8;
private static final int PRIVEXP_LENGTH = 2048 / 8;
private static final int P_LENGTH = 1024 / 8;
private static final int Q_LENGTH = 1024 / 8;
private static final int DP_LENGTH = 1024 / 8;
private static final int DQ_LENGTH = 1024 / 8;
private static final int QINV_LENGTH = 1024 / 8;

private static final BigInteger PUBEXP_0X03 = BigInteger.valueOf(0x03);

private static final BigInteger VERSION_2PRIMES = BigInteger.valueOf(0);

private static final AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER =
new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);

private static final int PLAINTEXT_BLOCKSIZE = 256 - 11;
private static final int CIPHERTEXT_BLOCKSIZE = 256;


//-----------------Key Generation Algorithm-----------------

/**
* key pair generation
*
* @return key pair
*/
public static AsymmetricCipherKeyPair generateKeyPair(){
return generateKeyPair(new SecureRandom());
}

public static AsymmetricCipherKeyPair generateKeyPair(SecureRandom random){
AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator();
kpGen.init(new RSAKeyGenerationParameters(PUBEXP_0X03, random, KEYSIZEBITS, CERTAINTY));
return kpGen.generateKeyPair();
}

// Retrieve public key in raw keys form
public static byte[] retrievePublicKey(byte[] privateKey) {

RSAPrivateCrtKeyParameters privKey = bytes2PrivKey_RawKey(privateKey);

BigInteger modulus = privKey.getModulus();
BigInteger exponent = privKey.getPublicExponent();

RSAKeyParameters pubKey = new RSAKeyParameters(false, modulus, exponent);

return pubKey2Bytes_RawKey(pubKey);
}


//-----------------Digital Signature Algorithm-----------------

/**
* signature generation
*
* @param data data to be signed
* @param privateKey private key
* @return signature
*/
public static byte[] sign(byte[] data, byte[] privateKey){
RSAPrivateCrtKeyParameters privKey = bytes2PrivKey_RawKey(privateKey);
return sign(data,privKey);
}

public static byte[] sign(byte[] data, CipherParameters params){

SHA256Digest digest = new SHA256Digest();
RSADigestSigner signer = new RSADigestSigner(digest);
signer.init(true, params);
signer.update(data, 0, data.length);
try {
return signer.generateSignature();
} catch (CryptoException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
}

/**
* verification
*
* @param data data to be signed
* @param publicKey public key
* @param signature signature to be verified
* @return true or false
*/
public static boolean verify(byte[] data, byte[] publicKey, byte[] signature){
RSAKeyParameters pubKey = bytes2PubKey_RawKey(publicKey);
return verify(data,pubKey,signature);
}

public static boolean verify(byte[] data, CipherParameters params, byte[] signature){

SHA256Digest digest = new SHA256Digest();
RSADigestSigner signer = new RSADigestSigner(digest);

signer.init(false, params);
signer.update(data, 0, data.length);
return signer.verifySignature(signature);
}


//-----------------Public Key Encryption Algorithm-----------------

/**
* encryption
*
* @param plainBytes plaintext
* @param publicKey public key
* @return ciphertext
*/
public static byte[] encrypt(byte[] plainBytes, byte[] publicKey){
RSAKeyParameters pubKey = bytes2PubKey_RawKey(publicKey);
return encrypt(plainBytes,pubKey);
}

public static byte[] encrypt(byte[] plainBytes, byte[] publicKey, SecureRandom random){

RSAKeyParameters pubKey = bytes2PubKey_RawKey(publicKey);
ParametersWithRandom params = new ParametersWithRandom(pubKey,random);

return encrypt(plainBytes,params);
}

public static byte[] encrypt(byte[] plainBytes, CipherParameters params){

int blockNum = (plainBytes.length % PLAINTEXT_BLOCKSIZE == 0) ? (plainBytes.length / PLAINTEXT_BLOCKSIZE)
: (plainBytes.length / PLAINTEXT_BLOCKSIZE + 1);
int inputLength;
byte[] result = new byte[blockNum * CIPHERTEXT_BLOCKSIZE];
byte[] buffer;

AsymmetricBlockCipher encryptor = new PKCS1Encoding(new RSAEngine());
encryptor.init(true, params);
try {
for (int i= 0; i < blockNum; i++) {
inputLength = ((plainBytes.length - i * PLAINTEXT_BLOCKSIZE) > PLAINTEXT_BLOCKSIZE)?
PLAINTEXT_BLOCKSIZE : (plainBytes.length - i * PLAINTEXT_BLOCKSIZE);
buffer = encryptor.processBlock(plainBytes, i * PLAINTEXT_BLOCKSIZE, inputLength);
System.arraycopy(buffer,0,
result, i * CIPHERTEXT_BLOCKSIZE, CIPHERTEXT_BLOCKSIZE);
}
} catch (InvalidCipherTextException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
return result;
}

/**
* decryption
*
* @param cipherBytes ciphertext
* @param privateKey private key
* @return plaintext
*/
public static byte[] decrypt(byte[] cipherBytes, byte[] privateKey){
RSAPrivateCrtKeyParameters privKey = bytes2PrivKey_RawKey(privateKey);
return decrypt(cipherBytes,privKey);
}

public static byte[] decrypt(byte[] cipherBytes, CipherParameters params){

if (cipherBytes.length % CIPHERTEXT_BLOCKSIZE != 0)
{
throw new com.jd.blockchain.crypto.CryptoException("ciphertext's length is wrong!");
}

int blockNum = cipherBytes.length / CIPHERTEXT_BLOCKSIZE;
int count = 0;
byte[] buffer;
byte[] plaintextWithZeros = new byte[blockNum * PLAINTEXT_BLOCKSIZE];
byte[] result;

AsymmetricBlockCipher decryptor = new PKCS1Encoding(new RSAEngine());
decryptor.init(false,params);
try {
for (int i = 0; i < blockNum; i++){
buffer = decryptor.processBlock(cipherBytes,i * CIPHERTEXT_BLOCKSIZE, CIPHERTEXT_BLOCKSIZE);
count += buffer.length;
System.arraycopy(buffer,0,plaintextWithZeros, i * PLAINTEXT_BLOCKSIZE, buffer.length);
}
} catch (InvalidCipherTextException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

result = new byte[count];
System.arraycopy(plaintextWithZeros,0,result,0,result.length);

return result;
}


/**
* This outputs the key in PKCS1v2 format.
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* }
*/
public static byte[] pubKey2Bytes_PKCS1(RSAKeyParameters pubKey)
{
ASN1EncodableVector v = new ASN1EncodableVector();

v.add(new ASN1Integer(pubKey.getModulus()));
v.add(new ASN1Integer(pubKey.getExponent()));

DERSequence pubKeySequence = new DERSequence(v);

byte[] result;

try {
result = pubKeySequence.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

return result;
}

public static byte[] pubKey2Bytes_PKCS8(RSAKeyParameters pubKey){

BigInteger modulus = pubKey.getModulus();
BigInteger exponent = pubKey.getExponent();

return KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER,
new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent));
}

public static byte[] pubKey2Bytes_RawKey(RSAKeyParameters pubKey){

BigInteger modulus = pubKey.getModulus();
BigInteger exponent = pubKey.getExponent();

byte[] exponentBytes = exponent.toByteArray();
byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);

return BytesUtils.concat(modulusBytes,exponentBytes);
}

public static RSAKeyParameters bytes2PubKey_PKCS1(byte[] pubKeyBytes) {

ASN1Sequence pubKeySequence = ASN1Sequence.getInstance(pubKeyBytes);

BigInteger modulus = ASN1Integer.getInstance(pubKeySequence.getObjectAt(0)).getValue();
BigInteger exponent = ASN1Integer.getInstance(pubKeySequence.getObjectAt(1)).getValue();

return new RSAKeyParameters(false, modulus, exponent);
}

public static RSAKeyParameters bytes2PubKey_PKCS8(byte[] pubKeyBytes) {

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyBytes);

KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

RSAPublicKey publicKey = null;
try {
publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (InvalidKeySpecException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

assert publicKey != null;

BigInteger exponent = publicKey.getPublicExponent();
BigInteger modulus = publicKey.getModulus();

return new RSAKeyParameters(false,modulus,exponent);
}

public static RSAKeyParameters bytes2PubKey_RawKey(byte[] pubKeyBytes) {

byte[] modulusBytes = new byte[MODULUS_LENGTH];
byte[] exponentBytes = new byte[pubKeyBytes.length - MODULUS_LENGTH];

System.arraycopy(pubKeyBytes,0, modulusBytes,0, MODULUS_LENGTH);

System.arraycopy(pubKeyBytes,MODULUS_LENGTH, exponentBytes,0,exponentBytes.length);

BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger exponent = new BigInteger(1, exponentBytes);

return new RSAKeyParameters(false,modulus,exponent);
}

/**
* This outputs the key in PKCS1v2 format.
* RSAPrivateKey ::= SEQUENCE {
* VERSION_2PRIMES Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER, -- (inverse of q) mod p
* otherPrimeInfos OtherPrimeInfos OPTIONAL
* }
*
* Version ::= INTEGER { two-prime(0), multi(1) }
* (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
*
* This routine is written to output PKCS1 version 2.1, private keys.
*/
public static byte[] privKey2Bytes_PKCS1(RSAPrivateCrtKeyParameters privKey)
{
ASN1EncodableVector v = new ASN1EncodableVector();

v.add(new ASN1Integer(VERSION_2PRIMES)); // version
v.add(new ASN1Integer(privKey.getModulus()));
v.add(new ASN1Integer(privKey.getPublicExponent()));
v.add(new ASN1Integer(privKey.getExponent()));
v.add(new ASN1Integer(privKey.getP()));
v.add(new ASN1Integer(privKey.getQ()));
v.add(new ASN1Integer(privKey.getDP()));
v.add(new ASN1Integer(privKey.getDQ()));
v.add(new ASN1Integer(privKey.getQInv()));

DERSequence privKeySequence = new DERSequence(v);

byte[] result;

try {
result = privKeySequence.getEncoded(ASN1Encoding.DER);
} catch (IOException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

return result;
}

public static byte[] privKey2Bytes_PKCS8(RSAPrivateCrtKeyParameters privKey){

BigInteger modulus = privKey.getModulus();
BigInteger pubExp = privKey.getPublicExponent();
BigInteger privExp = privKey.getExponent();
BigInteger p = privKey.getP();
BigInteger q = privKey.getQ();
BigInteger dP = privKey.getDP();
BigInteger dQ = privKey.getDQ();
BigInteger qInv = privKey.getQInv();

return KeyUtil.getEncodedPrivateKeyInfo(RSA_ALGORITHM_IDENTIFIER,
new RSAPrivateKey(modulus, pubExp, privExp, p, q, dP, dQ, qInv));
}

public static byte[] privKey2Bytes_RawKey(RSAPrivateCrtKeyParameters privKey){

BigInteger modulus = privKey.getModulus();
BigInteger pubExp = privKey.getPublicExponent();
BigInteger privExp = privKey.getExponent();
BigInteger p = privKey.getP();
BigInteger q = privKey.getQ();
BigInteger dP = privKey.getDP();
BigInteger dQ = privKey.getDQ();
BigInteger qInv = privKey.getQInv();

byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);
byte[] pubExpBytes = pubExp.toByteArray();
byte[] privExpBytes = bigInteger2Bytes(privExp,PRIVEXP_LENGTH);
byte[] pBytes = bigInteger2Bytes(p,P_LENGTH);
byte[] qBytes = bigInteger2Bytes(q,Q_LENGTH);
byte[] dPBytes = bigInteger2Bytes(dP,DP_LENGTH);
byte[] dQBytes = bigInteger2Bytes(dQ,DQ_LENGTH);
byte[] qInvBytes = bigInteger2Bytes(qInv,QINV_LENGTH);


return BytesUtils.concat(modulusBytes,pubExpBytes,privExpBytes,pBytes,qBytes,dPBytes,dQBytes,qInvBytes);
}

public static RSAPrivateCrtKeyParameters bytes2PrivKey_PKCS1(byte[] privKeyBytes){

ASN1Sequence priKeySequence = ASN1Sequence.getInstance(privKeyBytes);

BigInteger modulus = ASN1Integer.getInstance(priKeySequence.getObjectAt(1)).getValue();
BigInteger pubExp = ASN1Integer.getInstance(priKeySequence.getObjectAt(2)).getValue();
BigInteger privExp = ASN1Integer.getInstance(priKeySequence.getObjectAt(3)).getValue();
BigInteger p = ASN1Integer.getInstance(priKeySequence.getObjectAt(4)).getValue();
BigInteger q = ASN1Integer.getInstance(priKeySequence.getObjectAt(5)).getValue();
BigInteger dP = ASN1Integer.getInstance(priKeySequence.getObjectAt(6)).getValue();
BigInteger dQ = ASN1Integer.getInstance(priKeySequence.getObjectAt(7)).getValue();
BigInteger qInv = ASN1Integer.getInstance(priKeySequence.getObjectAt(8)).getValue();

return new RSAPrivateCrtKeyParameters(modulus, pubExp, privExp, p, q, dP, dQ, qInv);
}

public static RSAPrivateCrtKeyParameters bytes2PrivKey_PKCS8(byte[] privKeyBytes){

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyBytes);

KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

RSAPrivateCrtKeyImpl privateKey;
try {
privateKey = (RSAPrivateCrtKeyImpl) keyFactory.generatePrivate(keySpec);
} catch (InvalidKeySpecException e) {
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

assert privateKey != null;

BigInteger modulus = privateKey.getModulus();
BigInteger pubExp = privateKey.getPublicExponent();
BigInteger privExp = privateKey.getPrivateExponent();
BigInteger p = privateKey.getPrimeP();
BigInteger q = privateKey.getPrimeQ();
BigInteger dP = privateKey.getPrimeExponentP();
BigInteger dQ = privateKey.getPrimeExponentQ();
BigInteger qInv = privateKey.getCrtCoefficient();

return new RSAPrivateCrtKeyParameters(modulus, pubExp, privExp, p, q, dP, dQ, qInv);
}

public static RSAPrivateCrtKeyParameters bytes2PrivKey_RawKey(byte[] privKeyBytes){

byte[] modulusBytes = new byte[MODULUS_LENGTH];
byte[] pubExpBytes = new byte[privKeyBytes.length - MODULUS_LENGTH - PRIVEXP_LENGTH - P_LENGTH - Q_LENGTH
- DP_LENGTH - DQ_LENGTH - QINV_LENGTH];
byte[] privExpBytes = new byte[PRIVEXP_LENGTH];
byte[] pBytes = new byte[P_LENGTH];
byte[] qBytes = new byte[Q_LENGTH];
byte[] dPBytes = new byte[DP_LENGTH];
byte[] dQBytes = new byte[DQ_LENGTH];
byte[] qInvBytes = new byte[QINV_LENGTH];

System.arraycopy(privKeyBytes,0, modulusBytes,0, MODULUS_LENGTH);
System.arraycopy(privKeyBytes, MODULUS_LENGTH, pubExpBytes,0,pubExpBytes.length);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length,
privExpBytes,0,PRIVEXP_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH,
pBytes,0,P_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH,
qBytes,0,Q_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH +
Q_LENGTH, dPBytes,0,DP_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH +
Q_LENGTH + DP_LENGTH, dQBytes,0,DQ_LENGTH);
System.arraycopy(privKeyBytes,MODULUS_LENGTH + pubExpBytes.length + PRIVEXP_LENGTH + P_LENGTH +
Q_LENGTH + DP_LENGTH + DQ_LENGTH, qInvBytes,0,QINV_LENGTH);

BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger pubExp = new BigInteger(1, pubExpBytes);
BigInteger privExp = new BigInteger(1, privExpBytes);
BigInteger p = new BigInteger(1, pBytes);
BigInteger q = new BigInteger(1, qBytes);
BigInteger dP = new BigInteger(1, dPBytes);
BigInteger dQ = new BigInteger(1, dQBytes);
BigInteger qInv = new BigInteger(1, qInvBytes);

return new RSAPrivateCrtKeyParameters(modulus, pubExp, privExp, p, q, dP, dQ, qInv);
}

private static byte[] bigInteger2Bytes(BigInteger src, int length){

byte[] result = new byte[length];
byte[] srcBytes = src.toByteArray();
int srcLength = srcBytes.length;

if (srcLength > length) {
System.arraycopy(srcBytes,srcLength - length,
result,0, length);
} else {
System.arraycopy(srcBytes,0,
result,length - srcLength, length);
}

return result;
}
}

+ 352
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java View File

@@ -0,0 +1,352 @@
package test.com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.utils.io.BytesUtils;
import org.junit.Test;

import java.util.Random;

import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY;
import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: ECDSASignatureFunctionTest
* @description: JunitTest for ECDSASignatureFunction in SPI mode
* @date 2019-04-23, 09:37
*/
public class ECDSASignatureFunctionTest {

@Test
public void getAlgorithmTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("eCDsA");
assertNotNull(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("eedsa");
assertNull(algorithm);
}

@Test
public void generateKeyPairTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE);
assertEquals(65, pubKey.getRawKeyBytes().length);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertEquals(32, privKey.getRawKeyBytes().length);

assertEquals(algorithm.code(), pubKey.getAlgorithm());
assertEquals(algorithm.code(), privKey.getAlgorithm());

assertEquals(2 + 1 + 65, pubKey.toBytes().length);
assertEquals(2 + 1 + 32, privKey.toBytes().length);

byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes());
assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes());
}

@Test
public void retrievePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey);

assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType());
assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length);
assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm());
assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes());
}

@Test
public void signTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureBytes = signatureDigest.toBytes();

assertEquals(2 + 64, signatureBytes.length);
assertEquals(ClassicAlgorithm.ECDSA.code(), signatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
signatureDigest.getAlgorithm());

byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm());
byte[] rawSinatureBytes = signatureDigest.getRawDigest();
assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes);
}

@Test
public void verifyTest() {
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

assertTrue(signatureFunction.verify(signatureDigest, pubKey, data));
}

@Test
public void supportPrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

assertTrue(signatureFunction.supportPrivKey(privKeyBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] rawKeyBytes = privKey.getRawKeyBytes();
byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes);

assertFalse(signatureFunction.supportPrivKey(ripemd160PubKeyBytes));
}

@Test
public void resolvePrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes);

assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE);
assertEquals(32, resolvedPrivKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.ECDSA.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] rawKeyBytes = privKey.getRawKeyBytes();
byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolvePrivKey(ripemd160PubKeyBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportPubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

assertTrue(signatureFunction.supportPubKey(pubKeyBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawKeyBytes = pubKey.getRawKeyBytes();
byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes);

assertFalse(signatureFunction.supportPubKey(ripemd160PrivKeyBytes));
}

@Test
public void resolvePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes);

assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE);
assertEquals(65, resolvedPubKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.ECDSA.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawKeyBytes = pubKey.getRawKeyBytes();
byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolvePrivKey(ripemd160PrivKeyBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();
assertTrue(signatureFunction.supportDigest(signatureDigestBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] rawDigestBytes = signatureDigest.toBytes();
byte[] ripemd160SignatureBytes = BytesUtils.concat(algoBytes, rawDigestBytes);

assertFalse(signatureFunction.supportDigest(ripemd160SignatureBytes));
}

@Test
public void resolveDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("ECDSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();

SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes);

assertEquals(64, resolvedSignatureDigest.getRawDigest().length);
assertEquals(ClassicAlgorithm.ECDSA.code(), resolvedSignatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 22 & 0x00FF)),
resolvedSignatureDigest.getAlgorithm());
assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] rawDigestBytes = signatureDigest.getRawDigest();
byte[] ripemd160SignatureDigestBytes = BytesUtils.concat(algoBytes, rawDigestBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolveDigest(ripemd160SignatureDigestBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}
}

+ 488
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java View File

@@ -0,0 +1,488 @@
package test.com.jd.blockchain.crypto.service.classic;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.utils.io.BytesUtils;
import org.junit.Test;

import java.util.Random;

import static com.jd.blockchain.crypto.CryptoAlgorithm.*;
import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE;
import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC;
import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: RSACryptoFunctionTest
* @description: JunitTest for RSACryptoFunction in SPI mode
* @date 2019-04-23, 15:30
*/
public class RSACryptoFunctionTest {

@Test
public void getAlgorithmTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("Rsa");
assertNotNull(algorithm);

assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name());
assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code());

algorithm = Crypto.getAlgorithm("rsa2");
assertNull(algorithm);
}

@Test
public void generateKeyPairTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE);
assertEquals(257, pubKey.getRawKeyBytes().length);
assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE);
assertEquals(1153, privKey.getRawKeyBytes().length);

assertEquals(algorithm.code(), pubKey.getAlgorithm());
assertEquals(algorithm.code(), privKey.getAlgorithm());

assertEquals(2 + 1 + 257, pubKey.toBytes().length);
assertEquals(2 + 1 + 1153, privKey.toBytes().length);

byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawPubKeyBytes = pubKey.getRawKeyBytes();
byte[] rawPrivKeyBytes = privKey.getRawKeyBytes();
assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes());
assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes());
}

@Test
public void retrievePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey);

assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType());
assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length);
assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm());
assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes());
}

@Test
public void signTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureBytes = signatureDigest.toBytes();

assertEquals(2 + 256, signatureBytes.length);
assertEquals(algorithm.code(), signatureDigest.getAlgorithm());

assertEquals(ClassicAlgorithm.RSA.code(), signatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
signatureDigest.getAlgorithm());

byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm());
byte[] rawSinatureBytes = signatureDigest.getRawDigest();
assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes);
}

@Test
public void verifyTest() {
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();
SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

assertTrue(signatureFunction.verify(signatureDigest, pubKey, data));
}

@Test
public void encryptTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] ciphertextBytes = ciphertext.toBytes();
assertEquals(2 + 256, ciphertextBytes.length);
assertEquals(ClassicAlgorithm.RSA.code(), ciphertext.getAlgorithm());

assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
ciphertext.getAlgorithm());

byte[] algoBytes = BytesUtils.toBytes(ciphertext.getAlgorithm());
byte[] rawCiphertextBytes = ciphertext.getRawCiphertext();
assertArrayEquals(BytesUtils.concat(algoBytes, rawCiphertextBytes), ciphertextBytes);
}

@Test
public void decryptTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
PrivKey privKey = keyPair.getPrivKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] decryptedPlaintext = asymmetricEncryptionFunction.decrypt(privKey, ciphertext);

assertArrayEquals(data, decryptedPlaintext);
}

@Test
public void supportPrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

assertTrue(signatureFunction.supportPrivKey(privKeyBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] rawKeyBytes = privKey.getRawKeyBytes();
byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes);

assertFalse(signatureFunction.supportPrivKey(ripemd160PubKeyBytes));
}

@Test
public void resolvePrivKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();
byte[] privKeyBytes = privKey.toBytes();

PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes);

assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE);
assertEquals(1153, resolvedPrivKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedPrivKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedPrivKey.getAlgorithm());
assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE };
byte[] rawKeyBytes = privKey.getRawKeyBytes();
byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolvePrivKey(ripemd160PubKeyBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportPubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

assertTrue(signatureFunction.supportPubKey(pubKeyBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawKeyBytes = pubKey.getRawKeyBytes();
byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes);

assertFalse(signatureFunction.supportPubKey(ripemd160PrivKeyBytes));
}

@Test
public void resolvePubKeyTest() {

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();
byte[] pubKeyBytes = pubKey.toBytes();

PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes);

assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE);
assertEquals(257, resolvedPubKey.getRawKeyBytes().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedPubKey.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedPubKey.getAlgorithm());
assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE };
byte[] rawKeyBytes = pubKey.getRawKeyBytes();
byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolvePrivKey(ripemd160PrivKeyBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();
assertTrue(signatureFunction.supportDigest(signatureDigestBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] rawDigestBytes = signatureDigest.toBytes();
byte[] ripemd160SignatureBytes = BytesUtils.concat(algoBytes, rawDigestBytes);

assertFalse(signatureFunction.supportDigest(ripemd160SignatureBytes));
}

@Test
public void resolveDigestTest() {

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm);

AsymmetricKeypair keyPair = signatureFunction.generateKeypair();

PrivKey privKey = keyPair.getPrivKey();

SignatureDigest signatureDigest = signatureFunction.sign(privKey, data);

byte[] signatureDigestBytes = signatureDigest.toBytes();

SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes);

assertEquals(256, resolvedSignatureDigest.getRawDigest().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedSignatureDigest.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedSignatureDigest.getAlgorithm());
assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] rawDigestBytes = signatureDigest.getRawDigest();
byte[] ripemd160SignatureDigestBytes = BytesUtils.concat(algoBytes, rawDigestBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
signatureFunction.resolveDigest(ripemd160SignatureDigestBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

@Test
public void supportCiphertextTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] ciphertextBytes = ciphertext.toBytes();

assertTrue(asymmetricEncryptionFunction.supportCiphertext(ciphertextBytes));

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] rawCiphertextBytes = ciphertext.toBytes();
byte[] ripemd160CiphertextBytes = BytesUtils.concat(algoBytes, rawCiphertextBytes);

assertFalse(asymmetricEncryptionFunction.supportCiphertext(ripemd160CiphertextBytes));
}

@Test
public void resolveCiphertextTest() {

byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA");
assertNotNull(algorithm);

AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto
.getAsymmetricEncryptionFunction(algorithm);

AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair();

PubKey pubKey = keyPair.getPubKey();

Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data);

byte[] ciphertextBytes = ciphertext.toBytes();

Ciphertext resolvedCiphertext = asymmetricEncryptionFunction.resolveCiphertext(ciphertextBytes);

assertEquals(256, resolvedCiphertext.getRawCiphertext().length);
assertEquals(ClassicAlgorithm.RSA.code(), resolvedCiphertext.getAlgorithm());
assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)),
resolvedCiphertext.getAlgorithm());
assertArrayEquals(ciphertextBytes, resolvedCiphertext.toBytes());

algorithm = Crypto.getAlgorithm("ripemd160");
assertNotNull(algorithm);
byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm);
byte[] rawCiphertextBytes = ciphertext.getRawCiphertext();
byte[] ripemd160CiphertextBytes = BytesUtils.concat(algoBytes, rawCiphertextBytes);

Class<?> expectedException = CryptoException.class;
Exception actualEx = null;
try {
asymmetricEncryptionFunction.resolveCiphertext(ripemd160CiphertextBytes);
} catch (Exception e) {
actualEx = e;
}
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

}

+ 100
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java View File

@@ -0,0 +1,100 @@
package test.com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.utils.classic.AESUtils;
import com.jd.blockchain.utils.io.BytesUtils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;

import java.util.Random;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: AESUtilsTest
* @description: Tests for methods in AESUtils
* @date 2019-04-22, 16:06
*/
public class AESUtilsTest {

@Test
public void generateKeyTest(){
byte[] key = AESUtils.generateKey();
assertEquals(16,key.length);
key = AESUtils.generateKey("abc".getBytes());
assertArrayEquals(
Hex.decode("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".substring(0,32)),key);
}


@Test
public void encryptTest(){
String plaintext = "abc";
String key = "1234567890123456";
System.out.println(key.getBytes().length);
String iv = "1234567890123456";
String expectedCiphertextIn2ndBlock = "f479efae2d41d23227f61e675fced95c";

byte[] ciphertext = AESUtils.encrypt(plaintext.getBytes(),key.getBytes(),iv.getBytes());
byte[] expectedCiphertext = BytesUtils.concat(iv.getBytes(),Hex.decode(expectedCiphertextIn2ndBlock));
assertArrayEquals(expectedCiphertext,ciphertext);
}


@Test
public void decryptTest(){

Random random = new Random();
byte[] data = new byte[1024];
random.nextBytes(data);

byte[] key = AESUtils.generateKey();

byte[] ciphertext = AESUtils.encrypt(data,key);
byte[] plaintext = AESUtils.decrypt(ciphertext,key);

assertArrayEquals(data,plaintext);
}
//
//
// @Test
// public void encryptingPerformance() {
//
// byte[] data = new byte[1000];
// Random random = new Random();
// random.nextBytes(data);
//
// byte[] aesCiphertext = null;
//
// int count = 100000;
//
//
// byte[] aesKey = AESUtils.generateKey();
//
// System.out.println("=================== do AES encrypt test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// aesCiphertext = AESUtils.encrypt(data, aesKey);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("AES Encrypting Count=%s; Elapsed Times=%s; KBPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
//
// System.out.println("=================== do AES decrypt test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// AESUtils.decrypt(aesCiphertext, aesKey);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("AES Decrypting Count=%s; Elapsed Times=%s; KBPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
// }
}

+ 78
- 2
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ECDSAUtilsTest.java View File

@@ -2,16 +2,20 @@ package test.com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.utils.classic.ECDSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.FixedSecureRandom;
import org.junit.Test;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

import static org.junit.Assert.*;
@@ -110,6 +114,80 @@ public class ECDSAUtilsTest {
assertEquals("04" + xCoord + yCoord,Hex.toHexString(result).toUpperCase());
}

@Test
public void checkDeterministicValues(){
// https://crypto.stackexchange.com/questions/41316/complete-set-of-test-vectors-for-ecdsa-secp256k1
ECDomainParameters domainParams = ECDSAUtils.getDomainParams();
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
new BigInteger("ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f", 16),
domainParams);
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
domainParams.getCurve().decodePoint(Hex.decode("04" +
"779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcd" +
"e94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f")),
domainParams);

byte[] privKeyBytes = BigIntegerTo32Bytes(privKey.getD());
byte[] pubKeyBytes = ECDSAUtils.retrievePublicKey(privKeyBytes);

assertArrayEquals(pubKeyBytes,pubKey.getQ().getEncoded(false));

SecureRandom k = new FixedSecureRandom(Hex.decode("49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a"));
CipherParameters params = new ParametersWithRandom(privKey,k);

byte[] hashedMsg = Hex.decode("4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a");

byte[] signature = ECDSAUtils.sign(params,hashedMsg);

String r = "241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795";
String s = "021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e";
assertEquals(Hex.toHexString(signature),r + s);

assertTrue(ECDSAUtils.verify(pubKey,signature,hashedMsg));
}

@Test
public void performanceTest(){

int count = 10000;
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair();
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate();
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic();

byte[] signatureDigest = ECDSAUtils.sign(data,privKeyParams);

assertTrue(ECDSAUtils.verify(data,pubKeyParams,signatureDigest));

System.out.println("=================== do ECDSA sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ECDSAUtils.sign(data,privKeyParams);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ECDSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ECDSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ECDSAUtils.verify(data,pubKeyParams,signatureDigest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ECDSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}
}

// To convert BigInteger to byte[] whose length is 32
private static byte[] BigIntegerTo32Bytes(BigInteger b){
byte[] tmp = b.toByteArray();
@@ -122,6 +200,4 @@ public class ECDSAUtilsTest {
}
return result;
}


}

+ 72
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java View File

@@ -108,4 +108,76 @@ public class ED25519UtilsTest {
assertTrue(Ed25519Utils.verify(data,pubKeyBytes,signatureDigest));

}

@Test
public void performanceTest(){

int count = 10000;
byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair();
Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate();
Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic();

byte[] pubKeyBytes = pubKeyParams.getEncoded();
byte[] privKeyBytes = privKeyParams.getEncoded();

byte[] signatureDigest = ED25519Utils.sign(data,privKeyParams);

assertTrue(ED25519Utils.verify(data,pubKeyParams,signatureDigest));

System.out.println("=================== do ED25519 sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ED25519Utils.sign(data,privKeyParams);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ED25519 verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ED25519Utils.verify(data,pubKeyParams,signatureDigest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ED25519 sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Ed25519Utils.sign_512(data,privKeyBytes);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do ED25519 verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Ed25519Utils.verify(data,pubKeyBytes,signatureDigest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("ED25519 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

}

}

+ 32
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java View File

@@ -0,0 +1,32 @@
package test.com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.utils.classic.RIPEMD160Utils;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
* @author zhanglin33
* @title: RIPEMD160UtilsTest
* @description: Tests for the hash method in RIPEMD160Utils
* @date 2019-04-10, 16:54
*/
public class RIPEMD160UtilsTest {

@Test
public void hashTest() {

byte[] data1 = "a".getBytes();
byte[] data2 = "abc".getBytes();

byte[] result1 = RIPEMD160Utils.hash(data1);
byte[] result2 = RIPEMD160Utils.hash(data2);

String respectedResult1 = "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe";
String respectedResult2 = "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc";

assertEquals(respectedResult1, Hex.toHexString(result1));
assertEquals(respectedResult2, Hex.toHexString(result2));
}
}

+ 426
- 0
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java View File

@@ -0,0 +1,426 @@
package test.com.jd.blockchain.crypto.utils.classic;

import com.jd.blockchain.crypto.utils.classic.RSAUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.junit.Test;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Random;

import static org.junit.Assert.*;

/**
* @author zhanglin33
* @title: RSAUtilsTest
* @description: Tests for methods in RSAUtils
* @date 2019-04-11, 17:10
*/
public class RSAUtilsTest {

@Test
public void generateKeyPairTest(){
AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) kp.getPrivate();

byte[] pubKeyBytes_RawKey = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] pubKeyBytesConverted_RawKey =
RSAUtils.pubKey2Bytes_RawKey(RSAUtils.bytes2PubKey_RawKey(pubKeyBytes_RawKey));
assertArrayEquals(pubKeyBytes_RawKey,pubKeyBytesConverted_RawKey);

byte[] privKeyBytes_RawKey = RSAUtils.privKey2Bytes_RawKey(privKey);
byte[] privKeyBytesConverted_RawKey =
RSAUtils.privKey2Bytes_RawKey(RSAUtils.bytes2PrivKey_RawKey(privKeyBytes_RawKey));
assertArrayEquals(privKeyBytes_RawKey,privKeyBytesConverted_RawKey);

System.out.println(pubKeyBytes_RawKey.length);
System.out.println(privKeyBytes_RawKey.length);

byte[] pubKeyBytes_PKCS1 = RSAUtils.pubKey2Bytes_PKCS1(pubKey);
byte[] pubKeyBytesConverted_PKCS1 =
RSAUtils.pubKey2Bytes_PKCS1(RSAUtils.bytes2PubKey_PKCS1(pubKeyBytes_PKCS1));
assertArrayEquals(pubKeyBytes_PKCS1,pubKeyBytesConverted_PKCS1);

byte[] privKeyBytes_PKCS1 = RSAUtils.privKey2Bytes_PKCS1(privKey);
byte[] privKeyBytesConverted_PKCS1 =
RSAUtils.privKey2Bytes_PKCS1(RSAUtils.bytes2PrivKey_PKCS1(privKeyBytes_PKCS1));
assertArrayEquals(privKeyBytes_PKCS1,privKeyBytesConverted_PKCS1);

byte[] pubKeyBytes_PKCS8 = RSAUtils.pubKey2Bytes_PKCS8(pubKey);
byte[] pubKeyBytesConverted_PKCS8 =
RSAUtils.pubKey2Bytes_PKCS8(RSAUtils.bytes2PubKey_PKCS8(pubKeyBytes_PKCS8));
assertArrayEquals(pubKeyBytes_PKCS8,pubKeyBytesConverted_PKCS8);

byte[] privKeyBytes_PKCS8 = RSAUtils.privKey2Bytes_PKCS8(privKey);
byte[] privKeyBytesConverted_PKCS8 =
RSAUtils.privKey2Bytes_PKCS8(RSAUtils.bytes2PrivKey_PKCS8(privKeyBytes_PKCS8));
assertArrayEquals(privKeyBytes_PKCS8,privKeyBytesConverted_PKCS8);
}

@Test
public void retrievePublicKeyTest(){

AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair();
RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic();
RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) kp.getPrivate();

byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey(privKey);
byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey(pubKey);
byte[] retrievedPubKeyBytes = RSAUtils.retrievePublicKey(privKeyBytes);

assertArrayEquals(pubKeyBytes,retrievedPubKeyBytes);
}

@Test
public void signTest(){

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey);

byte[] signatureFromPrivKey = RSAUtils.sign(data, privKey);
byte[] signatureFromPrivKeyBytes = RSAUtils.sign(data, privKeyBytes);

assertNotNull(signatureFromPrivKey);
assertEquals(2048 / 8, signatureFromPrivKey.length);
assertArrayEquals(signatureFromPrivKeyBytes,signatureFromPrivKey);
}

@Test
public void verifyTest(){

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
AsymmetricKeyParameter pubKey = keyPair.getPublic();
byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey((RSAKeyParameters) pubKey);

byte[] signature = RSAUtils.sign(data,privKey);

boolean isValidFromPubKey = RSAUtils.verify(data, pubKey, signature);
boolean isValidFromPubKeyBytes = RSAUtils.verify(data, pubKeyBytes, signature);

assertTrue(isValidFromPubKey);
assertTrue(isValidFromPubKeyBytes);
}

@Test
public void encryptTest(){

byte[] data = new byte[246];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter pubKey = keyPair.getPublic();
byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey((RSAKeyParameters) pubKey);

byte[] ciphertextFromPubKey = RSAUtils.encrypt(data,pubKey);
byte[] ciphertextFromPubKeyBytes = RSAUtils.encrypt(data,pubKeyBytes);

assertEquals(512,ciphertextFromPubKey.length);
assertEquals(512,ciphertextFromPubKeyBytes.length);
}

@Test
public void decryptTest(){

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter pubKey = keyPair.getPublic();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey);

byte[] data;
for (int i = 1; i < 1024; i++) {
data = new byte[i];
Random random = new Random();
random.nextBytes(data);
byte[] ciphertext = RSAUtils.encrypt(data, pubKey);

byte[] plaintextFromPrivKey = RSAUtils.decrypt(ciphertext, privKey);
byte[] plaintextFromPrivKeyBytes = RSAUtils.decrypt(ciphertext, privKeyBytes);

assertArrayEquals(data, plaintextFromPrivKey);
assertArrayEquals(data, plaintextFromPrivKeyBytes);
}
}


@Test
public void performanceTest(){

int count = 10000;
byte[] data = new byte[128];
Random random = new Random();
random.nextBytes(data);

AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair();
AsymmetricKeyParameter privKey = keyPair.getPrivate();
AsymmetricKeyParameter pubKey = keyPair.getPublic();

byte[] signature = RSAUtils.sign(data,privKey);
byte[] ciphertext = RSAUtils.encrypt(data,pubKey);

System.out.println("=================== do RSA sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.sign(data,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do RSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.verify(data,pubKey,signature);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do RSA encrypt test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.encrypt(data,pubKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Encrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do RSA decrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.decrypt(ciphertext,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("RSA Decrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}
}

@Test
public void encryptionConsistencyTest(){

int count = 10000;
byte[] data = new byte[222];
Random random = new Random();
random.nextBytes(data);

KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
assert keyPairGen != null;
keyPairGen.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();

RSAKeyParameters pubKey = RSAUtils.bytes2PubKey_PKCS8(publicKeyBytes);
RSAPrivateCrtKeyParameters privKey = RSAUtils.bytes2PrivKey_PKCS8(privateKeyBytes);

Cipher cipher;
byte[] ciphertext = null;
byte[] plaintext = null;

System.out.println("=================== do BouncyCastle-based RSA encrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
ciphertext = RSAUtils.encrypt(data,pubKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Encrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

assert ciphertext != null;
System.out.println("=================== do BouncyCastle-based RSA decrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
plaintext = RSAUtils.decrypt(ciphertext,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Decrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do JDK-based RSA encrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
ciphertext = cipher.doFinal(data);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Encrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do JDK-based RSA decrypt test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
plaintext = cipher.doFinal(ciphertext);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Decrypting Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}


assertArrayEquals(data,plaintext);
assertArrayEquals(data,plaintext);
}

@Test
public void signatureConsistencyTest() {

int count = 10000;
byte[] data = new byte[222];
Random random = new Random();
random.nextBytes(data);

KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
assert keyPairGen != null;
keyPairGen.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();

byte[] signature = null;
boolean isValid = false;

RSAKeyParameters pubKey = RSAUtils.bytes2PubKey_PKCS8(publicKeyBytes);
RSAPrivateCrtKeyParameters privKey = RSAUtils.bytes2PrivKey_PKCS8(privateKeyBytes);

System.out.println("=================== do BouncyCastle-based RSA sign test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
signature = RSAUtils.sign(data,privKey);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do BouncyCastle-based RSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
isValid = RSAUtils.verify(data,pubKey,signature);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("BouncyCastle-based RSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}




System.out.println("=================== do JDK-based RSA sign test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(privateKey);
signer.update(data);
signature = signer.sign();
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do JDK-based RSA verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
Signature verifier = Signature.getInstance("SHA256withRSA");
verifier.initVerify(publicKey);
verifier.update(data);
isValid = verifier.verify(signature);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("JDK-based RSA Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println(isValid);

}
}

+ 1
- 1
source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SHA256UtilsTest.java View File

@@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals;
/**
* @author zhanglin33
* @title: SHA256UtilsTest
* @description: Tests for the hash method in ECDSAUtils
* @description: Tests for the hash method in SHA256Utils
* @date 2019-04-09, 16:18
*/
public class SHA256UtilsTest {


+ 5
- 13
source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java View File

@@ -72,7 +72,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
throw new CryptoException("This key is not SM2 private key!");
}

// 验证密文数据的算法标识对应SM2签名算法,并且原始摘要长度为64字节
// 验证密文数据的算法标识对应SM2算法,并且密文符合长度要求
if (ciphertext.getAlgorithm() != SM2.code()
|| rawCiphertextBytes.length < ECPOINT_SIZE + HASHDIGEST_SIZE) {
throw new CryptoException("This is not SM2 ciphertext!");
@@ -89,14 +89,6 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
return new PubKey(SM2, rawPubKeyBytes);
}

// @Override
// public byte[] retrievePubKey(byte[] privKeyBytes) {
//
// byte[] rawPrivKeyBytes = resolvePrivKey(privKeyBytes).getRawKeyBytes();
// byte[] rawPubKeyBytes = SM2Utils.retrievePublicKey(rawPrivKeyBytes);
// return new PubKey(SM2, rawPubKeyBytes).toBytes();
// }

@Override
public boolean supportPrivKey(byte[] privKeyBytes) {
// 验证输入字节数组长度=算法标识长度+密钥类型长度+密钥长度,密钥数据的算法标识对应SM2算法,并且密钥类型是私钥
@@ -109,7 +101,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportPrivKey(privKeyBytes)) {
return new PrivKey(privKeyBytes);
} else {
throw new CryptoException("privKeyBytes is invalid!");
throw new CryptoException("privKeyBytes are invalid!");
}
}

@@ -125,7 +117,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportPubKey(pubKeyBytes)) {
return new PubKey(pubKeyBytes);
} else {
throw new CryptoException("pubKeyBytes is invalid!");
throw new CryptoException("pubKeyBytes are invalid!");
}
}

@@ -141,7 +133,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportCiphertext(ciphertextBytes)) {
return new AsymmetricCiphertext(ciphertextBytes);
} else {
throw new CryptoException("ciphertextBytes is invalid!");
throw new CryptoException("ciphertextBytes are invalid!");
}
}

@@ -200,7 +192,7 @@ public class SM2CryptoFunction implements AsymmetricEncryptionFunction, Signatur
if (supportDigest(digestBytes)) {
return new SignatureDigest(digestBytes);
} else {
throw new CryptoException("digestBytes is invalid!");
throw new CryptoException("digestBytes are invalid!");
}
}



+ 25
- 4
source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java View File

@@ -11,11 +11,12 @@ import org.bouncycastle.crypto.params.ParametersWithIV;


import java.security.SecureRandom;
import java.util.Arrays;

public class SM4Utils {

// SM4 supports 128-bit secret key
private static final int KEY_LENGTH = 128;
// SM4 supports 128-bit(16 bytes) secret key
private static final int KEY_SIZE = 128 / 8;
// One block contains 16 bytes
private static final int BLOCK_SIZE = 16;
// Initial vector's size is 16 bytes
@@ -33,12 +34,17 @@ public class SM4Utils {

// To provide secure randomness and key length as input
// to prepare generate private key
keyGenerator.init(new KeyGenerationParameters(new SecureRandom(), KEY_LENGTH));
keyGenerator.init(new KeyGenerationParameters(new SecureRandom(), KEY_SIZE * 8));

// To generate key
return keyGenerator.generateKey();
}

public static byte[] generateKey(byte[] seed){
byte[] hash = SM3Utils.hash(seed);
return Arrays.copyOf(hash, KEY_SIZE);
}


/**
* encryption
@@ -56,6 +62,16 @@ public class SM4Utils {
throw new CryptoException("plaintext is null!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

if (iv.length != IV_SIZE)
{
throw new CryptoException("iv's length is wrong!");
}

// To get the value padded into input
int padding = 16 - plainBytes.length % BLOCK_SIZE;
// The plaintext with padding value
@@ -105,11 +121,16 @@ public class SM4Utils {
}

// To ensure that the ciphertext's length is integral multiples of 16 bytes
if ( cipherBytes.length % BLOCK_SIZE != 0 )
if (cipherBytes.length % BLOCK_SIZE != 0)
{
throw new CryptoException("ciphertext's length is wrong!");
}

if (secretKey.length != KEY_SIZE)
{
throw new CryptoException("secretKey's length is wrong!");
}

byte[] iv = new byte[IV_SIZE];
System.arraycopy(cipherBytes,0,iv,0,BLOCK_SIZE);



+ 0
- 1
source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java View File

@@ -484,5 +484,4 @@ public class SM2CyptoFunctionTest {
assertNotNull(actualEx);
assertTrue(expectedException.isAssignableFrom(actualEx.getClass()));
}

}

+ 42
- 70
source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/utils/SM2UtilsTest.java View File

@@ -13,6 +13,8 @@ import org.junit.Test;

import com.jd.blockchain.crypto.utils.sm.SM2Utils;

import java.util.Random;

public class SM2UtilsTest {

@Test
@@ -160,74 +162,44 @@ public class SM2UtilsTest {
// }
//
//
// @Test
// public void signingPerformace(){
//
// byte[] data = new byte[1000];
// Random random = new Random();
// random.nextBytes(data);
//
// int count = 10000;
//
// byte[] sm2Digest = null;
// byte[] ed25519Digest = null;
//
// AsymmetricCipherKeyPair keyPair = SM2Utils.generateKeyPair();
// ECPublicKeyParameters ecPub = (ECPublicKeyParameters) keyPair.getPublic();
// ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters) keyPair.getPrivate();
//
// System.out.println("=================== do SM2 sign test ===================");
//
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// sm2Digest = SM2Utils.sign(data,ecPriv);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("SM2 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
// System.out.println("=================== do SM2 verify test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// SM2Utils.verify(data,ecPub,sm2Digest);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("SM2 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
// KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
// KeyPair ed25519KeyPair = keyPairGenerator.generateKeyPair();
// EdDSAPrivateKey privKey = (EdDSAPrivateKey) ed25519KeyPair.getPrivate();
// EdDSAPublicKey pubKey = (EdDSAPublicKey) ed25519KeyPair.getPublic();
//
// System.out.println("=================== do ED25519 sign test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// ed25519Digest = Ed25519Utils.sign_512(data,privKey.getSeed());
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("ED25519 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
//
// System.out.println("=================== do ED25519 verify test ===================");
// for (int r = 0; r < 5; r++) {
// System.out.println("------------- round[" + r + "] --------------");
// long startTS = System.currentTimeMillis();
// for (int i = 0; i < count; i++) {
// Ed25519Utils.verify(data,pubKey.getAbyte(),ed25519Digest);
// }
// long elapsedTS = System.currentTimeMillis() - startTS;
// System.out.println(String.format("ED25519 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
// (count * 1000.00D) / elapsedTS));
// }
// }
@Test
public void signingPerformace(){

byte[] data = new byte[1024];
Random random = new Random();
random.nextBytes(data);

int count = 10000;

byte[] sm2Digest = null;

AsymmetricCipherKeyPair keyPair = SM2Utils.generateKeyPair();
ECPublicKeyParameters ecPub = (ECPublicKeyParameters) keyPair.getPublic();
ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters) keyPair.getPrivate();

System.out.println("=================== do SM2 sign test ===================");

for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
sm2Digest = SM2Utils.sign(data,ecPriv);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("SM2 Signing Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}

System.out.println("=================== do SM2 verify test ===================");
for (int r = 0; r < 5; r++) {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
SM2Utils.verify(data,ecPub,sm2Digest);
}
long elapsedTS = System.currentTimeMillis() - startTS;
System.out.println(String.format("SM2 Verifying Count=%s; Elapsed Times=%s; TPS=%.2f", count, elapsedTS,
(count * 1000.00D) / elapsedTS));
}
}
}

+ 28
- 0
source/utils/utils-common/src/test/java/test/my/utils/security/RSAUtilsTest.java View File

@@ -1,10 +1,19 @@
package test.my.utils.security;
import static com.jd.blockchain.utils.security.RSAUtils.ALG_RSA;
import static org.junit.Assert.*;
import java.io.UnsupportedEncodingException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;
import com.jd.blockchain.utils.codec.HexUtils;
@@ -57,4 +66,23 @@ public class RSAUtilsTest {
}
@Test
public void generateKeyPairTest() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
byte[] pubKey = publicKey.getEncoded();
byte[] privKey = privateKey.getEncoded();
System.out.println(Base64.toBase64String(pubKey));
System.out.println(Base64.toBase64String(privKey));
System.out.println(Hex.toHexString(pubKey));
System.out.println(Hex.toHexString(privKey));
}
}

Loading…
Cancel
Save