Browse Source

integrate RSA and ECDSA into spi

tags/1.0.0
zhanglin33 5 years ago
parent
commit
58bb7a8418
13 changed files with 1579 additions and 89 deletions
  1. +4
    -3
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ClassicCryptoService.java
  2. +107
    -16
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunction.java
  3. +2
    -4
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java
  4. +142
    -24
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java
  5. +161
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java
  6. +5
    -6
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java
  7. +352
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/ECDSASignatureFunctionTest.java
  8. +488
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java
  9. +100
    -0
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/AESUtilsTest.java
  10. +189
    -18
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java
  11. +5
    -13
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM2CryptoFunction.java
  12. +24
    -3
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java
  13. +0
    -1
      source/crypto/crypto-sm/src/test/java/test/com/jd/blockchain/crypto/service/sm/SM2CyptoFunctionTest.java

+ 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;
}
}

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

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

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

}

@Override
@@ -69,7 +68,7 @@ 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!");
}
@@ -106,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
@@ -140,6 +138,7 @@ public class ED25519SignatureFunction implements SignatureFunction {

@Override
public AsymmetricKeypair generateKeypair() {

// 调用ED25519算法的密钥生成算法生成公私钥对priKey和pubKey,返回密钥对
AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair();
Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate();
@@ -148,6 +147,5 @@ public class ED25519SignatureFunction implements SignatureFunction {
byte[] privKeyBytes = privKeyParams.getEncoded();
byte[] pubKeyBytes = pubKeyParams.getEncoded();
return new AsymmetricKeypair(new PubKey(ED25519, pubKeyBytes), new PrivKey(ED25519, privKeyBytes));

}
}

+ 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));
}
}

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

@@ -1,10 +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: AES/CBC/PKCS7Padding symmetric encryption algorithm
* @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;
}
}

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

@@ -31,8 +31,8 @@ import java.security.spec.X509EncodedKeySpec;
/**
* @author zhanglin33
* @title: RSAUtils
* @description: RSA2048 encryption(ECB) and signature algorithms with SHA256,
* and keys are output in both PKCS1v2 format and PKCS8
* @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 {
@@ -48,6 +48,8 @@ public class RSAUtils {
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 =
@@ -69,11 +71,8 @@ public class RSAUtils {
}

public static AsymmetricCipherKeyPair generateKeyPair(SecureRandom random){

AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator();

BigInteger exponent = BigInteger.valueOf(0x11);
kpGen.init(new RSAKeyGenerationParameters(exponent, random, KEYSIZEBITS, CERTAINTY));
kpGen.init(new RSAKeyGenerationParameters(PUBEXP_0X03, random, KEYSIZEBITS, CERTAINTY));
return kpGen.generateKeyPair();
}



+ 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));
// }
// }
}

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

@@ -42,6 +42,9 @@ public class RSAUtilsTest {
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));
@@ -163,7 +166,7 @@ public class RSAUtilsTest {
public void performanceTest(){

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

@@ -172,6 +175,7 @@ public class RSAUtilsTest {
AsymmetricKeyParameter pubKey = keyPair.getPublic();

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

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

@@ -179,7 +183,7 @@ public class RSAUtilsTest {
System.out.println("------------- round[" + r + "] --------------");
long startTS = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
RSAUtils.sign(data,privKey);
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,
@@ -197,11 +201,37 @@ public class RSAUtilsTest {
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 consistencyTest(){
public void encryptionConsistencyTest(){

int count = 10000;
byte[] data = new byte[222];
Random random = new Random();
random.nextBytes(data);
@@ -226,30 +256,171 @@ public class RSAUtilsTest {

Cipher cipher;
byte[] ciphertext = null;
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();
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;
byte[] plaintext = RSAUtils.decrypt(ciphertext,privKey);
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() {

ciphertext = RSAUtils.encrypt(data,pubKey);
int count = 10000;
byte[] data = new byte[222];
Random random = new Random();
random.nextBytes(data);

KeyPairGenerator keyPairGen = null;
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
plaintext = cipher.doFinal(ciphertext);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException e) {
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);

assertArrayEquals(data,plaintext);
}
}

+ 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!");
}
}



+ 24
- 3
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
@@ -110,6 +126,11 @@ public class SM4Utils {
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()));
}

}

Loading…
Cancel
Save