Browse Source

fix RSA bugs and add RSA consistent test with jdk’s RSA

tags/1.0.0
zhanglin33 6 years ago
parent
commit
019973b84f
6 changed files with 122 additions and 135 deletions
  1. +3
    -23
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java
  2. +2
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RIPEMD160HashFunction.java
  3. +2
    -1
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/SHA256HashFunction.java
  4. +10
    -0
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/AESUtils.java
  5. +33
    -101
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java
  6. +72
    -9
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java

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

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

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

}
@@ -76,7 +75,6 @@ public class ED25519SignatureFunction implements SignatureFunction {
}

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

@@ -84,21 +82,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 +97,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!");
}
}

@@ -129,7 +114,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 +129,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!");
}
}

@@ -162,11 +147,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);
}



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



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

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

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

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

@@ -114,9 +114,8 @@ public class RSAUtils {
try {
return signer.generateSignature();
} catch (CryptoException e) {
e.printStackTrace();
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
return null;
}

/**
@@ -177,14 +176,14 @@ public class RSAUtils {
encryptor.init(true, params);
try {
for (int i= 0; i < blockNum; i++) {
inputLength = ((plainBytes.length - i * PLAINTEXT_BLOCKSIZE) > i * PLAINTEXT_BLOCKSIZE)?
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) {
e.printStackTrace();
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}
return result;
}
@@ -274,19 +273,8 @@ public class RSAUtils {
BigInteger modulus = pubKey.getModulus();
BigInteger exponent = pubKey.getExponent();

byte[] modulusBytes = new byte[MODULUS_LENGTH];
byte[] exponentBytes = exponent.toByteArray();

byte[] encodedModulusBytes = modulus.toByteArray();
int encodedModulusLength = encodedModulusBytes.length;

if (encodedModulusLength > MODULUS_LENGTH) {
System.arraycopy(encodedModulusBytes,encodedModulusLength - MODULUS_LENGTH,
modulusBytes,0, MODULUS_LENGTH);
} else {
System.arraycopy(encodedModulusBytes,0,
modulusBytes,MODULUS_LENGTH - encodedModulusLength, MODULUS_LENGTH);
}
byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);

return BytesUtils.concat(modulusBytes,exponentBytes);
}
@@ -309,15 +297,14 @@ public class RSAUtils {
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

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

assert publicKey != null;
@@ -416,86 +403,15 @@ public class RSAUtils {
BigInteger dQ = privKey.getDQ();
BigInteger qInv = privKey.getQInv();

byte[] modulusBytes = new byte[MODULUS_LENGTH];
byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH);
byte[] pubExpBytes = pubExp.toByteArray();
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];

byte[] encodedModulusBytes = modulus.toByteArray();
byte[] encodedPrivExpBytes = privExp.toByteArray();
byte[] encodedPBytes = p.toByteArray();
byte[] encodedQBytes = q.toByteArray();
byte[] encodedDPBytes = dP.toByteArray();
byte[] encodedDQBytes = dQ.toByteArray();
byte[] encodedQInvBytes = qInv.toByteArray();

int encodedModulusLength = encodedModulusBytes.length;
int encodedPrivExpBytesLength = encodedPrivExpBytes.length;
int encodedPBytesLength = encodedPBytes.length;
int encodedQBytesLength = encodedQBytes.length;
int encodedDPBytesLength = encodedDPBytes.length;
int encodedDQBytesLength = encodedDQBytes.length;
int encodedQInvBytesLength = encodedQInvBytes.length;

if (encodedModulusLength > MODULUS_LENGTH) {
System.arraycopy(encodedModulusBytes,encodedModulusLength - MODULUS_LENGTH,
modulusBytes,0, MODULUS_LENGTH);
} else {
System.arraycopy(encodedModulusBytes,0,
modulusBytes,MODULUS_LENGTH - encodedModulusLength, MODULUS_LENGTH);
}

if (encodedPrivExpBytesLength > PRIVEXP_LENGTH) {
System.arraycopy(encodedPrivExpBytes,encodedPrivExpBytesLength - PRIVEXP_LENGTH,
privExpBytes,0, PRIVEXP_LENGTH);
} else {
System.arraycopy(encodedPrivExpBytes,0,
privExpBytes,PRIVEXP_LENGTH - encodedPrivExpBytesLength, PRIVEXP_LENGTH);
}

if (encodedPBytesLength > P_LENGTH) {
System.arraycopy(encodedPBytes,encodedPBytesLength - P_LENGTH,
pBytes,0, P_LENGTH);
} else {
System.arraycopy(encodedPBytes,0,
pBytes,P_LENGTH - encodedPBytesLength, P_LENGTH);
}

if (encodedQBytesLength > Q_LENGTH) {
System.arraycopy(encodedQBytes,encodedQBytesLength - Q_LENGTH,
qBytes,0, Q_LENGTH);
} else {
System.arraycopy(encodedQBytes,0,
qBytes,Q_LENGTH - encodedQBytesLength, Q_LENGTH);
}

if (encodedDPBytesLength > DP_LENGTH) {
System.arraycopy(encodedDPBytes,encodedDPBytesLength - DP_LENGTH,
dPBytes,0, DP_LENGTH);
} else {
System.arraycopy(encodedDPBytes,0,
dPBytes,DP_LENGTH - encodedDPBytesLength, DP_LENGTH);
}
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);

if (encodedDQBytesLength > DQ_LENGTH) {
System.arraycopy(encodedDQBytes,encodedDQBytesLength - DQ_LENGTH,
dQBytes,0, DQ_LENGTH);
} else {
System.arraycopy(encodedDQBytes,0,
dQBytes,DQ_LENGTH - encodedDQBytesLength, DQ_LENGTH);
}

if (encodedQInvBytesLength > QINV_LENGTH) {
System.arraycopy(encodedQInvBytes,encodedQInvBytesLength - QINV_LENGTH,
qInvBytes,0, QINV_LENGTH);
} else {
System.arraycopy(encodedQInvBytes,0,
qInvBytes,QINV_LENGTH - encodedQInvBytesLength, QINV_LENGTH);
}

return BytesUtils.concat(modulusBytes,pubExpBytes,privExpBytes,pBytes,qBytes,dPBytes,dQBytes,qInvBytes);
}
@@ -524,15 +440,14 @@ public class RSAUtils {
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e);
}

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

assert privateKey != null;
@@ -587,4 +502,21 @@ public class RSAUtils {

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

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

@@ -7,6 +7,13 @@ 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.*;
@@ -131,22 +138,24 @@ public class RSAUtilsTest {
@Test
public void decryptTest(){

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

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

byte[] ciphertext = RSAUtils.encrypt(data,pubKey);
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);
byte[] plaintextFromPrivKey = RSAUtils.decrypt(ciphertext, privKey);
byte[] plaintextFromPrivKeyBytes = RSAUtils.decrypt(ciphertext, privKeyBytes);

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


@@ -189,4 +198,58 @@ public class RSAUtilsTest {
(count * 1000.00D) / elapsedTS));
}
}

@Test
public void consistencyTest(){

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

assert ciphertext != null;
byte[] plaintext = RSAUtils.decrypt(ciphertext,privKey);
assertArrayEquals(data,plaintext);

ciphertext = RSAUtils.encrypt(data,pubKey);

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

assertArrayEquals(data,plaintext);
}
}

Loading…
Cancel
Save