英文:
Cannot match AES-GCM specification vectors with Java Crypto library
问题
I am trying to use the Java Crypto library as a reference for another application. To make sure I was getting correct results from the library I ran some sample vectors from the AES-GCM specification to compare the results against the library results.
我正在尝试使用Java加密库作为另一个应用程序的参考。为了确保我从库中获得了正确的结果,我运行了一些来自AES-GCM规范的示例向量,以将结果与库的结果进行比较。
I am able to get the simplest vector from the specification working, but any of the more complex vectors produce results which do not match the specification.
我能够使规范中最简单的向量正常工作,但更复杂的向量产生的结果与规范不匹配。
Test case 1, which passes, uses the following code:
测试案例1通过,使用以下代码:
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("0", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("0", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] cipherText = cipher.doFinal();
Test case 2 simply adds 16B of zeros as AAD:
测试案例2简单地将16B的零添加为AAD:
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("0", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("0", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] aad = stringToByteArray("0", 16);
cipher.updateAAD(aad);
byte[] cipherText = cipher.doFinal();
This second vector and other more complicated vectors I am unable to get to match. Can someone familiar with Crypto point out where my reference code is making a mistake?
我无法使这第二个向量和其他更复杂的向量匹配。熟悉加密的人能指出我的参考代码哪里出错吗?
Full source code available here: AesGcmSampleVectors on Github
完整的源代码在这里可用:AesGcmSampleVectors on Github
Edit: The Github source code has been updated to reflect the correct output, and has added a passing example of test vector 4 from the GCM specification.
编辑:Github源代码已更新以反映正确的输出,并添加了通过的GCM规范测试向量4的示例。
英文:
I am trying to use the Java Crypto library as a reference for another application. To make sure I was getting correct results from the library I ran some sample vectors from the AES-GCM specification to compare the results against the library results.
I am able to get the simplest vector from the specification working, but any of the more complex vectors produce results which do not match the specification.
Test case 1, which passes, uses the following code:
cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("0", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("0", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] cipherText = cipher.doFinal();
Test case 2 simply adds 16B of zeros as AAD:
cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("0", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("0", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] aad = stringToByteArray("0", 16);
cipher.updateAAD(aad);
byte[] cipherText = cipher.doFinal();
This second vector and other more complicated vectors I am unable to get to match. Can someone familiar with Crypto point out where my reference code is making a mistake?
Full source code available here: AesGcmSampleVectors on Github
Edit: The Github source code has been updated to reflect the correct output, and has added a passing example of test vector 4 from the GCM
specification.
答案1
得分: 1
第二个测试案例没有使用AAD,但是使用了16个0x00值的明文(你似乎混淆了明文和AAD):
K 00000000000000000000000000000000
P 00000000000000000000000000000000
IV 000000000000000000000000
...
C 0388dace60b6a392f328c2b971b2fe78
T ab6e47d42cec13bdf53a67b21257bddf
此外,需要考虑到Java将密文和标签进行拼接。以下代码实现了这一点,并成功执行:
...
byte[] expected = stringToByteArray("0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf", 32); // Fix 1: Java concatenates ciphertext and Tag
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("0", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("0", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
//byte[] aad = stringToByteArray("0", 12); // Fix 2: No AAD specified
//cipher.updateAAD(aad);
byte[] plaintext = stringToByteArray("0", 16); // Fix 3 specified plaintext: 16 0x00 values
byte[] cipherText = cipher.doFinal(plaintext);
if (Arrays.equals(cipherText, expected)) {
System.out.println("Vectors compared OK");
} else {
System.out.println("Vectors compared failed");
System.out.print("Expected:");
printByteArray(expected);
System.out.print("Received:");
printByteArray(cipherText);
}
...
AAD在第四个测试案例中被指定,如下所示:
K feffe9928665731c6d6a8f9467308308
P d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
A feedfacedeadbeeffeedfacedeadbeefabaddad2
IV cafebabefacedbaddecaf888
...
C 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
T 5bc94fbc3221a5db94fae95ae7121a47
需要按照以下方式实现(现在需要调用updateAAD()
函数):
byte[] expected = stringToByteArray("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e0915bc94fbc3221a5db94fae95ae7121a47", 76);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("cafebabefacedbaddecaf888", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("feffe9928665731c6d6a8f9467308308", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] aad = stringToByteArray("feedfacedeadbeeffeedfacedeadbeefabaddad2", 20);
cipher.updateAAD(aad);
byte[] plaintext = stringToByteArray("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", 60);
byte[] cipherText = cipher.doFinal(plaintext);
if (Arrays.equals(cipherText, expected)) {
System.out.println("Vectors compared OK");
} else {
System.out.println("Vectors compared failed");
System.out.print("Expected:");
printByteArray(expected);
System.out.print("Received:");
printByteArray(cipherText);
}
英文:
The second test case uses no AAD but a plaintext of 16 0x00 values (you seem to confuse plaintext and AAD):
K 00000000000000000000000000000000
P 00000000000000000000000000000000
IV 000000000000000000000000
...
C 0388dace60b6a392f328c2b971b2fe78
T ab6e47d42cec13bdf53a67b21257bddf
Furthermore, it must be taken into account that Java concatenates ciphertext and tag. The following code implements this correctly and is executed successfully:
...
byte[] expected = stringToByteArray("0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf", 32); // Fix 1: Java concatenates ciphertext and Tag
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("0", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("0", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
//byte[] aad = stringToByteArray("0", 12); // Fix 2: No AAD specified
//cipher.updateAAD(aad);
byte[] plaintext = stringToByteArray("0", 16); // Fix 3 specified plaintext: 16 0x00 values
byte[] cipherText = cipher.doFinal(plaintext);
if (Arrays.equals(cipherText, expected)) {
System.out.println("Vectors compared OK");
} else {
System.out.println("Vectors compared failed");
System.out.print("Expected:");
printByteArray(expected);
System.out.print("Received:");
printByteArray(cipherText);
}
...
AAD are specified e.g. in the fourth test case:
K feffe9928665731c6d6a8f9467308308
P d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
A feedfacedeadbeeffeedfacedeadbeefabaddad2
IV cafebabefacedbaddecaf888
...
C 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
T 5bc94fbc3221a5db94fae95ae7121a47
which is to be implemented as follows (now the updateAAD()
call is required):
byte[] expected = stringToByteArray("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e0915bc94fbc3221a5db94fae95ae7121a47", 76);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, stringToByteArray("cafebabefacedbaddecaf888", 12));
SecretKeySpec secretKey = new SecretKeySpec(stringToByteArray("feffe9928665731c6d6a8f9467308308", 16), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] aad = stringToByteArray("feedfacedeadbeeffeedfacedeadbeefabaddad2", 20);
cipher.updateAAD(aad);
byte[] plaintext = stringToByteArray("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", 60);
byte[] cipherText = cipher.doFinal(plaintext);
if (Arrays.equals(cipherText, expected)) {
System.out.println("Vectors compared OK");
} else {
System.out.println("Vectors compared failed");
System.out.print("Expected:");
printByteArray(expected);
System.out.print("Received:");
printByteArray(cipherText);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论