From 08110bbc3fddd7c7d9b8106dc3401e2b080d3de6 Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Fri, 29 Mar 2019 11:49:02 +0800 Subject: [PATCH] fix wrong implementations of AESEncryptionFunction and SM4EncryptionFunction in stream encrypting/decrypting --- .../service/classic/AESEncryptionFunction.java | 25 ++++--- .../crypto/service/sm/SM4EncryptionFunction.java | 87 ++++++++++++++++++---- 2 files changed, 87 insertions(+), 25 deletions(-) diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/AESEncryptionFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/AESEncryptionFunction.java index 5a4a1539..939eef78 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/AESEncryptionFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/AESEncryptionFunction.java @@ -21,6 +21,7 @@ public class AESEncryptionFunction implements SymmetricEncryptionFunction { private static final int KEY_SIZE = 128 / 8; private static final int BLOCK_SIZE = 128 / 8; + // AES-ECB private static final int PLAINTEXT_BUFFER_LENGTH = 256; private static final int CIPHERTEXT_BUFFER_LENGTH = 256 + 16 + 2; @@ -52,7 +53,7 @@ public class AESEncryptionFunction implements SymmetricEncryptionFunction { public void encrypt(SymmetricKey key, InputStream in, OutputStream out) { // 读输入流得到明文,加密,密文数据写入输出流 try { - // TODO: 错误地使用 available 方法; + byte[] buffBytes = new byte[PLAINTEXT_BUFFER_LENGTH]; @@ -65,15 +66,16 @@ public class AESEncryptionFunction implements SymmetricEncryptionFunction { int len; int i; - while((len=in.read(buffBytes)) > 0){ + while((len=in.read(buffBytes)) > 0) { padding = (byte) (PLAINTEXT_BUFFER_LENGTH - len); i = len; - while (i < plaintextWithPadding.length){ + while (i < plaintextWithPadding.length) { plaintextWithPadding[i] = padding; i++; } out.write(encrypt(key,plaintextWithPadding).toBytes()); } +// // TODO: 错误地使用 available 方法; // int size = in.available(); // if (size < 1){ // throw new CryptoException("The input is null!"); @@ -127,14 +129,14 @@ public class AESEncryptionFunction implements SymmetricEncryptionFunction { // 读输入流得到密文数据,解密,明文写入输出流 try { byte[] buffBytes = new byte[CIPHERTEXT_BUFFER_LENGTH]; - byte[] plaintextWithPadding = new byte[PLAINTEXT_BUFFER_LENGTH + 1]; + byte[] plaintextWithPadding; byte padding; byte[] plaintext; int len,i; - while ((len = in.read(buffBytes)) > 0){ - if (len != CIPHERTEXT_BUFFER_LENGTH){ + while ((len = in.read(buffBytes)) > 0) { + if (len != CIPHERTEXT_BUFFER_LENGTH) { throw new CryptoException("inputStream's length is wrong!"); } if (!supportCiphertext(buffBytes)) { @@ -143,17 +145,18 @@ public class AESEncryptionFunction implements SymmetricEncryptionFunction { plaintextWithPadding = decrypt(key,resolveCiphertext(buffBytes)); - if (plaintextWithPadding.length != (PLAINTEXT_BUFFER_LENGTH +1)){ - throw new CryptoException("The decrypted plaintext is valid"); + if (plaintextWithPadding.length != (PLAINTEXT_BUFFER_LENGTH + 1)) { + throw new CryptoException("The decrypted plaintext is invalid"); } - padding = plaintextWithPadding[PLAINTEXT_BUFFER_LENGTH]; i = PLAINTEXT_BUFFER_LENGTH; + while ((PLAINTEXT_BUFFER_LENGTH - padding) < i) { - while ((PLAINTEXT_BUFFER_LENGTH - padding) < i){ - + if (plaintextWithPadding[i] != padding) { + throw new CryptoException("The inputSteam padding is invalid!"); + } i--; } plaintext = new byte[PLAINTEXT_BUFFER_LENGTH - padding]; diff --git a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM4EncryptionFunction.java b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM4EncryptionFunction.java index d4766af5..59fdfb90 100644 --- a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM4EncryptionFunction.java +++ b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/service/sm/SM4EncryptionFunction.java @@ -20,6 +20,10 @@ public class SM4EncryptionFunction implements SymmetricEncryptionFunction { private static final int KEY_SIZE = 128 / 8; private static final int BLOCK_SIZE = 128 / 8; + // SM4-CBC + private static final int PLAINTEXT_BUFFER_LENGTH = 256; + private static final int CIPHERTEXT_BUFFER_LENGTH = 256 + 32 + 2; + private static final int SYMMETRICKEY_LENGTH = ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + KEY_SIZE; SM4EncryptionFunction() { @@ -49,12 +53,32 @@ public class SM4EncryptionFunction implements SymmetricEncryptionFunction { // 读输入流得到明文,加密,密文数据写入输出流 try { - byte[] sm4Data = new byte[in.available()]; - in.read(sm4Data); - in.close(); + byte[] buffBytes = new byte[PLAINTEXT_BUFFER_LENGTH]; + + // The final byte of plaintextWithPadding represents the length of padding in the first 256 bytes, + // and the padded value in hexadecimal + byte[] plaintextWithPadding = new byte[buffBytes.length + 1]; + + byte padding; + + int len; + int i; - out.write(encrypt(key, sm4Data).toBytes()); - out.close(); + while((len=in.read(buffBytes)) > 0) { + padding = (byte) (PLAINTEXT_BUFFER_LENGTH - len); + i = len; + while (i < plaintextWithPadding.length) { + plaintextWithPadding[i] = padding; + i++; + } + out.write(encrypt(key,plaintextWithPadding).toBytes()); + } +// byte[] sm4Data = new byte[in.available()]; +// in.read(sm4Data); +// in.close(); +// +// out.write(encrypt(key, sm4Data).toBytes()); +// out.close(); } catch (IOException e) { throw new CryptoException(e.getMessage(), e); } @@ -94,16 +118,51 @@ public class SM4EncryptionFunction implements SymmetricEncryptionFunction { public void decrypt(SymmetricKey key, InputStream in, OutputStream out) { // 读输入流得到密文数据,解密,明文写入输出流 try { - byte[] sm4Data = new byte[in.available()]; - in.read(sm4Data); - in.close(); - - if (!supportCiphertext(sm4Data)) { - throw new CryptoException("InputStream is not valid SM4 ciphertext!"); + byte[] buffBytes = new byte[CIPHERTEXT_BUFFER_LENGTH]; + byte[] plaintextWithPadding; + + byte padding; + byte[] plaintext; + + int len,i; + while ((len = in.read(buffBytes)) > 0) { + if (len != CIPHERTEXT_BUFFER_LENGTH) { + throw new CryptoException("inputStream's length is wrong!"); + } + if (!supportCiphertext(buffBytes)) { + throw new CryptoException("InputStream is not valid SM4 ciphertext!"); + } + + plaintextWithPadding = decrypt(key,resolveCiphertext(buffBytes)); + + if (plaintextWithPadding.length != (PLAINTEXT_BUFFER_LENGTH + 1)) { + throw new CryptoException("The decrypted plaintext is invalid"); + } + + padding = plaintextWithPadding[PLAINTEXT_BUFFER_LENGTH]; + i = PLAINTEXT_BUFFER_LENGTH; + + while ((PLAINTEXT_BUFFER_LENGTH - padding) < i) { + + if (plaintextWithPadding[i] != padding) { + throw new CryptoException("The inputSteam padding is invalid!"); + } + i--; + } + plaintext = new byte[PLAINTEXT_BUFFER_LENGTH - padding]; + System.arraycopy(plaintextWithPadding,0,plaintext,0,plaintext.length); + out.write(plaintext); } - - out.write(decrypt(key, resolveCiphertext(sm4Data))); - out.close(); +// byte[] sm4Data = new byte[in.available()]; +// in.read(sm4Data); +// in.close(); +// +// if (!supportCiphertext(sm4Data)) { +// throw new CryptoException("InputStream is not valid SM4 ciphertext!"); +// } +// +// out.write(decrypt(key, resolveCiphertext(sm4Data))); +// out.close(); } catch (IOException e) { throw new CryptoException(e.getMessage(), e); }