diff --git a/pom.xml b/pom.xml index 78276731d511f7e970124981734763162edb9766..bf75badd0902574ff76c78b8949f7c439ea7c409 100644 --- a/pom.xml +++ b/pom.xml @@ -5,12 +5,12 @@ com.jd.blockchain jdchain-parent - 1.1.4.RELEASE - ../../project/parent + 1.1.5.RELEASE + ../project/parent com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE pom diff --git a/utils-common/pom.xml b/utils-common/pom.xml index 8d8bf5096f9c7418fb66d5dae85aeb153b1e05a7..e6d2751c91f4651774824d58d6762930318a3ea6 100644 --- a/utils-common/pom.xml +++ b/utils-common/pom.xml @@ -5,7 +5,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-common diff --git a/utils-crypto-base/pom.xml b/utils-crypto-base/pom.xml index c5321dabef9151cf2f94487235ec78e663093965..1d4f0f3622e58a65cd0fcdd2f4a13b9f76f1676e 100644 --- a/utils-crypto-base/pom.xml +++ b/utils-crypto-base/pom.xml @@ -5,7 +5,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-crypto-base diff --git a/utils-crypto-classic/pom.xml b/utils-crypto-classic/pom.xml index 1d2ce95888ce536fb240dc6b09e3af8408592882..eef3ac06969861636b7c2af76e444b0a3d7df4bf 100644 --- a/utils-crypto-classic/pom.xml +++ b/utils-crypto-classic/pom.xml @@ -5,7 +5,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-crypto-classic diff --git a/utils-crypto-classic/src/main/java/utils/crypto/classic/AESUtils.java b/utils-crypto-classic/src/main/java/utils/crypto/classic/AESUtils.java index 0bf60eac9785cd76eac27494608b3683275d89c0..240e5fa150075396e3d6d018b25bfad523fc04dc 100644 --- a/utils-crypto-classic/src/main/java/utils/crypto/classic/AESUtils.java +++ b/utils-crypto-classic/src/main/java/utils/crypto/classic/AESUtils.java @@ -7,7 +7,6 @@ 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; @@ -132,31 +131,41 @@ public class AESUtils { } // To get the value padded into input - int padding = 16 - length % BLOCK_SIZE; - // The plaintext with padding value - byte[] plainBytesWithPadding = new byte[length + padding]; - System.arraycopy(plainBytes, offset, plainBytesWithPadding, 0, 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, length); + byte padding = getAESPadding(length); + int lengthWithPadding = length + padding; + + // 加密的明文输入数组,有 2 部分组成:原始明文 + PKCS7填充; + byte[] input = new byte[lengthWithPadding]; + System.arraycopy(plainBytes, offset, input, 0, length); + // PKCS7填充; + PKCS7PaddingUtils.addPadding(input, length, padding); + + // 加密的密文输出数组,由 2 部分组成:IV + 密文; + byte[] output = new byte[IV_SIZE + lengthWithPadding]; + + // The IV locates on the first block of ciphertext + System.arraycopy(iv, 0, output, 0, IV_SIZE); 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 - int blockCount = plainBytesWithPadding.length / BLOCK_SIZE; + int blockCount = lengthWithPadding / BLOCK_SIZE; + int blockOffset; + for (int i = 0; i < blockCount; i++) { - encryptor.processBlock(plainBytesWithPadding, i * BLOCK_SIZE, output, (i + 1) * BLOCK_SIZE); + blockOffset = i * BLOCK_SIZE; + encryptor.processBlock(input, blockOffset, output, IV_SIZE + blockOffset); } - // The IV locates on the first block of ciphertext - System.arraycopy(iv, 0, output, 0, BLOCK_SIZE); return output; } + public static byte getAESPadding(int dataLength) { + return (byte) (16 - dataLength % BLOCK_SIZE); + } + /** * 计算密文长度(包括填充);
* @@ -218,8 +227,9 @@ public class AESUtils { decryptor.init(false, new ParametersWithIV(new KeyParameter(secretKey), iv)); byte[] outputWithPadding = new byte[length - BLOCK_SIZE]; // To decrypt the input in CBC mode - for (int i = 1; i < length / BLOCK_SIZE; i++) { - decryptor.processBlock(cipherBytes, i * BLOCK_SIZE, outputWithPadding, (i - 1) * BLOCK_SIZE); + int blockcount = length / BLOCK_SIZE; + for (int i = 1; i < blockcount; i++) { + decryptor.processBlock(cipherBytes, offset + i * BLOCK_SIZE, outputWithPadding, (i - 1) * BLOCK_SIZE); } int p = outputWithPadding[outputWithPadding.length - 1]; diff --git a/utils-crypto-classic/src/main/java/utils/crypto/classic/PKCS7PaddingUtils.java b/utils-crypto-classic/src/main/java/utils/crypto/classic/PKCS7PaddingUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..398ad317a9fb639d7bffdea5a85bdec3badf901a --- /dev/null +++ b/utils-crypto-classic/src/main/java/utils/crypto/classic/PKCS7PaddingUtils.java @@ -0,0 +1,52 @@ +package utils.crypto.classic; + +import org.bouncycastle.crypto.InvalidCipherTextException; + +/** + * PKCS7 填充: + *

+ * + * 假设块大小为 C ,目标数组需要填充 n 个字节后长度才能对其到整块,那么填充的 n 个字节每个的值都是 n;
+ * 如果目标数据本身已经对齐了,则填充一个完整的块长度的数据,填充的 C 个字节每个的值都是 C; + */ +public class PKCS7PaddingUtils { + + /** + * 向目标数组填充; + * + * @param target 要填充的数组; + * @param paddingOffset 填充的起始位置; + * @param paddingCode 填充值;同时,也是填充的字节长度; + * @return + */ + public static int addPadding(byte[] target, int paddingOffset, byte paddingCode) { + int i = 0; + while (i < paddingCode) { + target[paddingOffset + i] = paddingCode; + i++; + } + + return paddingCode; + } + + /** + * return the number of pad bytes present in the block. + */ + public int padCount(byte[] in) throws InvalidCipherTextException { + int count = in[in.length - 1] & 0xff; + byte countAsbyte = (byte) count; + + // constant time version + boolean failed = (count > in.length | count == 0); + + for (int i = 0; i < in.length; i++) { + failed |= (in.length - i <= count) & (in[i] != countAsbyte); + } + + if (failed) { + throw new InvalidCipherTextException("pad block corrupted"); + } + + return count; + } +} \ No newline at end of file diff --git a/utils-crypto-classic/src/test/java/test/utils/crypto/classic/AESUtilsTest.java b/utils-crypto-classic/src/test/java/test/utils/crypto/classic/AESUtilsTest.java index 2c2c34202b506802852d437b0241ca81c1643773..ea56d6649dba97978dd8d5fecff1f6a523984c1b 100644 --- a/utils-crypto-classic/src/test/java/test/utils/crypto/classic/AESUtilsTest.java +++ b/utils-crypto-classic/src/test/java/test/utils/crypto/classic/AESUtilsTest.java @@ -19,81 +19,89 @@ import static org.junit.Assert.assertEquals; */ public class AESUtilsTest { - @Test - public void generateKeyTest(){ - byte[] key = AESUtils.generateKey(); - assertEquals(16,key.length); - key = AESUtils.generateKey(BytesUtils.toBytes("abc")); - assertArrayEquals( - Hex.decode("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".substring(0,32)),key); - } - - - @Test - public void encryptTest(){ - String plaintext = "abc"; - String key = "1234567890123456"; - String iv = "1234567890123456"; - String expectedCiphertextIn2ndBlock = "f479efae2d41d23227f61e675fced95c"; - - byte[] ciphertext = AESUtils.encrypt(BytesUtils.toBytes(plaintext), - BytesUtils.toBytes(key), BytesUtils.toBytes(iv)); - byte[] expectedCiphertext = BytesUtils.concat(BytesUtils.toBytes(iv),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); - } - - - 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)); - } - } + @Test + public void generateKeyTest() { + byte[] key = AESUtils.generateKey(); + assertEquals(16, key.length); + key = AESUtils.generateKey(BytesUtils.toBytes("abc")); + assertArrayEquals( + Hex.decode("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".substring(0, 32)), key); + } + + @Test + public void encryptTest() { + String plaintext = "abc"; + String key = "1234567890123456"; + String iv = "1234567890123456"; + String expectedCiphertextIn2ndBlock = "f479efae2d41d23227f61e675fced95c"; + + byte[] ciphertext = AESUtils.encrypt(BytesUtils.toBytes(plaintext), BytesUtils.toBytes(key), + BytesUtils.toBytes(iv)); + byte[] expectedCiphertext = BytesUtils.concat(BytesUtils.toBytes(iv), Hex.decode(expectedCiphertextIn2ndBlock)); + assertArrayEquals(expectedCiphertext, ciphertext); + } + + @Test + public void decryptTest() { + Random random = new Random(); + byte[] data = new byte[171]; + random.nextBytes(data); + + byte[] key = AESUtils.generateKey(); + + byte[] cipherbytes = AESUtils.encrypt(data, key); + byte[] plainbytes = AESUtils.decrypt(cipherbytes, key); + + assertArrayEquals(data, plainbytes); + + // 验证待偏移量参数的解密方法; + byte[] complexBytes = BytesUtils.concat(data, cipherbytes); + plainbytes = AESUtils.decrypt(complexBytes, data.length, cipherbytes.length, key); + assertArrayEquals(data, plainbytes); + + byte[] data2 = new byte[688]; + random.nextBytes(data2); + complexBytes = BytesUtils.concat(data, data2); + + cipherbytes = AESUtils.encrypt(complexBytes, data.length, data2.length, key); + plainbytes = AESUtils.decrypt(cipherbytes, key); + assertArrayEquals(data2, plainbytes); + } + + 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)); + } + } } diff --git a/utils-crypto-sm/pom.xml b/utils-crypto-sm/pom.xml index 115deacf03ecce7460abd2a3e3f757634c2bb622..38a7903b4197f113300cdbda25146470a520e8cf 100644 --- a/utils-crypto-sm/pom.xml +++ b/utils-crypto-sm/pom.xml @@ -5,7 +5,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-crypto-sm diff --git a/utils-serialize/pom.xml b/utils-serialize/pom.xml index d1a85c3d9b8727297608d28349342407eedd33f1..e3df61c5346adb02f10c0f8a62a7c461b0b1c913 100644 --- a/utils-serialize/pom.xml +++ b/utils-serialize/pom.xml @@ -4,7 +4,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-serialize diff --git a/utils-test/pom.xml b/utils-test/pom.xml index 8500e90641e79d5ccf86ca219692c504e586e289..9167c94f6d7a676a97397b30a788420ae34ae422 100644 --- a/utils-test/pom.xml +++ b/utils-test/pom.xml @@ -4,7 +4,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-test diff --git a/utils-web-server/pom.xml b/utils-web-server/pom.xml index 4de04eb755504f823c8a993241517d14eddf16ec..4ef233cc0c7879a6ecb97e611775adcdced4e3a4 100644 --- a/utils-web-server/pom.xml +++ b/utils-web-server/pom.xml @@ -4,7 +4,7 @@ com.jd.utils utils - 2.1.0-SNAPSHOT + 2.0.3.RELEASE utils-web-server