Browse Source

add RSA encryption and tests

tags/1.0.0
zhanglin33 6 years ago
parent
commit
532a67b102
4 changed files with 143 additions and 6 deletions
  1. +101
    -3
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java
  2. +1
    -1
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RIPEMD160UtilsTest.java
  3. +40
    -1
      source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java
  4. +1
    -1
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java

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

@@ -7,7 +7,10 @@ import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.*; import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.digests.SHA256Digest; 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.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
@@ -28,7 +31,7 @@ import java.security.spec.X509EncodedKeySpec;
/** /**
* @author zhanglin33 * @author zhanglin33
* @title: RSAUtils * @title: RSAUtils
* @description: RSA2048 encryption and signature algorithms with SHA256,
* @description: RSA2048 encryption(ECB) and signature algorithms with SHA256,
* and keys are output in both PKCS1v2 format and PKCS8 * and keys are output in both PKCS1v2 format and PKCS8
* @date 2019-03-25, 17:20 * @date 2019-03-25, 17:20
*/ */
@@ -47,7 +50,11 @@ public class RSAUtils {


private static final BigInteger VERSION_2PRIMES = BigInteger.valueOf(0); 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 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 Generation Algorithm-----------------
@@ -136,6 +143,96 @@ public class RSAUtils {
} }




//-----------------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) > i * 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();
}
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. * This outputs the key in PKCS1v2 format.
* RSAPublicKey ::= SEQUENCE { * RSAPublicKey ::= SEQUENCE {
@@ -304,7 +401,8 @@ public class RSAUtils {
BigInteger dQ = privKey.getDQ(); BigInteger dQ = privKey.getDQ();
BigInteger qInv = privKey.getQInv(); BigInteger qInv = privKey.getQInv();


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


public static byte[] privKey2Bytes_RawKey(RSAPrivateCrtKeyParameters privKey){ public static byte[] privKey2Bytes_RawKey(RSAPrivateCrtKeyParameters privKey){


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

@@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals;
/** /**
* @author zhanglin33 * @author zhanglin33
* @title: RIPEMD160UtilsTest * @title: RIPEMD160UtilsTest
* @description: Tests for the hash method in RIPEMD160
* @description: Tests for the hash method in RIPEMD160Utils
* @date 2019-04-10, 16:54 * @date 2019-04-10, 16:54
*/ */
public class RIPEMD160UtilsTest { public class RIPEMD160UtilsTest {


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

@@ -14,7 +14,7 @@ import static org.junit.Assert.*;
/** /**
* @author zhanglin33 * @author zhanglin33
* @title: RSAUtilsTest * @title: RSAUtilsTest
* @description: TODO
* @description: Tests for methods in RSAUtils
* @date 2019-04-11, 17:10 * @date 2019-04-11, 17:10
*/ */
public class RSAUtilsTest { public class RSAUtilsTest {
@@ -110,6 +110,45 @@ public class RSAUtilsTest {
assertTrue(isValidFromPubKeyBytes); 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(){

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

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



@Test @Test
public void performanceTest(){ public void performanceTest(){


+ 1
- 1
source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM4Utils.java View File

@@ -105,7 +105,7 @@ public class SM4Utils {
} }


// To ensure that the ciphertext's length is integral multiples of 16 bytes // 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!"); throw new CryptoException("ciphertext's length is wrong!");
} }


Loading…
Cancel
Save