+ *
+ * 假设块大小为 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 @@