Repository: commons-crypto Updated Branches: refs/heads/master aad8c55a4 -> 3466943e4
CRYPTO-125: Add new testcases for GCM cipher Closes #76 from kexianda/ut_gcm Project: http://git-wip-us.apache.org/repos/asf/commons-crypto/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-crypto/commit/3466943e Tree: http://git-wip-us.apache.org/repos/asf/commons-crypto/tree/3466943e Diff: http://git-wip-us.apache.org/repos/asf/commons-crypto/diff/3466943e Branch: refs/heads/master Commit: 3466943e4552474ab681d7852dbfa62c74d8e1ce Parents: aad8c55 Author: Xianda Ke <xianda...@intel.com> Authored: Mon Nov 20 08:38:23 2017 +0800 Committer: Sun Dapeng <s...@apache.org> Committed: Mon Nov 20 08:38:37 2017 +0800 ---------------------------------------------------------------------- .../commons/crypto/cipher/GcmCipherTest.java | 673 +++++++++++++++++++ 1 file changed, 673 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/3466943e/src/test/java/org/apache/commons/crypto/cipher/GcmCipherTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/crypto/cipher/GcmCipherTest.java b/src/test/java/org/apache/commons/crypto/cipher/GcmCipherTest.java new file mode 100644 index 0000000..e2ca660 --- /dev/null +++ b/src/test/java/org/apache/commons/crypto/cipher/GcmCipherTest.java @@ -0,0 +1,673 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.crypto.cipher; + +import java.nio.ByteBuffer; +import java.security.Key; +import java.util.Arrays; +import java.util.Properties; +import java.util.Random; + +import org.apache.commons.crypto.utils.Utils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.crypto.AEADBadTagException; +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.bind.DatatypeConverter; + +public class GcmCipherTest { + + Properties props = null; + String cipherClass = null; + String transformation = "AES/GCM/NoPadding"; + + private String[] kHex; + private String[] pHex; + private String[] ivHex; + private String[] aadHex; + private String[] cHex; + private String[] tHex; + + @Before + public void setup() { + //init + cipherClass = OpenSslCipher.class.getName(); + + props = new Properties(); + props.setProperty(CryptoCipherFactory.CLASSES_KEY, + cipherClass); + initTestData(); + } + + /** + * NIST AES Test Vectors + * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + */ + @Test + public void testGcmNistCase2() { + // key length: 16 bytes + // plain text length: 16 bytes + // iv length: 12 bytes + // aad length: 0 bytes + + String kHex = "00000000000000000000000000000000"; + String pHex = "00000000000000000000000000000000"; + String ivHex = "000000000000000000000000"; + String aadHex = ""; + + String cHex = "0388dace60b6a392f328c2b971b2fe78"; + String tHex = "ab6e47d42cec13bdf53a67b21257bddf"; + + testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex); + } + + @Test + public void testGcmNistCase4() { + // key length: 16 bytes + // plain text length: 60 bytes + // iv length: 12 bytes + // aad length: 20 bytes + + String kHex = "feffe9928665731c6d6a8f9467308308"; + String pHex = "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39"; + String ivHex = "cafebabefacedbaddecaf888"; + String aadHex = "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2"; + + String cHex = "42831ec2217774244b7221b784d0d49c" + + "e3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa05" + + "1ba30b396a0aac973d58e091"; + String tHex = "5bc94fbc3221a5db94fae95ae7121a47"; + + testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex); + } + + @Test + public void testGcmNistCase5(){ + // key length: 16 bytes + // plain text length: 60 bytes + // iv length: 8 bytes + // aad length: 20 bytes + + String kHex = "feffe9928665731c6d6a8f9467308308"; + + String pHex = "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39"; + + String ivHex ="cafebabefacedbad"; // 64bits < 96bits + + String aadHex="feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2"; + + String cHex = "61353b4c2806934a777ff51fa22a4755" + + "699b2a714fcdc6f83766e5f97b6c7423" + + "73806900e49f24b22b097544d4896b42" + + "4989b5e1ebac0f07c23f4598"; + + String tHex = "3612d2e79e3b0785561be14aaca2fccb"; + + testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex); + } + + @Test + public void testGcmNistCase6(){ + // key length: 16 bytes + // plain text length: 60 bytes + // iv length: 60 bytes + // aad length: 20 bytes + + String kHex = "feffe9928665731c6d6a8f9467308308"; + + String pHex = "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39"; + + String ivHex ="9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728" + + "c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b"; // > 96bits + + String aadHex="feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2"; + + String cHex = "8ce24998625615b603a033aca13fb894" + + "be9112a5c3a211a8ba262a3cca7e2ca7" + + "01e4a9a4fba43c90ccdcb281d48c7c6f" + + "d62875d2aca417034c34aee5"; + + String tHex = "619cc5aefffe0bfa462af43c1699d050"; + + testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex); + testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex); + } + + @Test + public void testGcmNistCases(){ + for(int i = 0; i < kHex.length; i++) { + testGcmEncryption(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]); + testGcmDecryption(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]); + testGcmByteBuffer(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]); + testGcmReturnDataAfterTagVerified(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]); + testGcmArbitraryLengthUpdate(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]); + } + } + + @Test(expected = AEADBadTagException.class) + public void testGcmTamperedData() throws Exception { + + Random r = new Random(); + int textLength = r.nextInt(1024*1024); + int ivLength = r.nextInt(60); + int keyLength = 16; + int tagLength = 128; // bits + int aadLength = r.nextInt(128); + + byte[] keyBytes = new byte[keyLength]; + byte[] plainBytes = new byte[textLength]; + byte[] ivBytes = new byte[ivLength]; + byte[] aadBytes = new byte[aadLength]; + + r.nextBytes(keyBytes); + r.nextBytes(plainBytes); + r.nextBytes(ivBytes); + r.nextBytes(aadBytes); + + byte[] encOutput = new byte[plainBytes.length + (tagLength >> 3)]; + byte[] decOutput = new byte[plainBytes.length]; + + try { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + + GCMParameterSpec iv = new GCMParameterSpec(tagLength, ivBytes); + c.init(Cipher.ENCRYPT_MODE, key, iv); + c.updateAAD(aadBytes); + c.doFinal(plainBytes, 0, plainBytes.length, encOutput, 0); + c.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + + // Tamper the encrypted data. + encOutput[0] = (byte)(encOutput[0] + 1); + + try { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + + GCMParameterSpec iv = new GCMParameterSpec(tagLength, ivBytes); + c.init(Cipher.DECRYPT_MODE, key, iv); + c.updateAAD(aadBytes); + c.doFinal(encOutput, 0, encOutput.length, decOutput, 0); + c.close(); + } + catch (AEADBadTagException ex) { + Assert.assertTrue("Tag mismatch!".equals(ex.getMessage())); + throw ex; + } + } + + @Test + public void testGMac() { + // for GMAC, aad is the input data, + // tag is the digest message + + Random r = new Random(); + byte[] keyBytes = new byte[32]; + byte[] input = new byte[0]; // no input for GMAC + byte[] ivBytes = new byte[16]; + + byte[] tag_orig = new byte[16]; // JDK's tag + byte[] tag = new byte[16]; + + // aad is the data to be hashed + byte[] aad = new byte[r.nextInt() % 1000 + 1000 ]; + + r.nextBytes(keyBytes); + r.nextBytes(input); + r.nextBytes(ivBytes); + r.nextBytes(aad); + + try { + { + Cipher c = Cipher.getInstance(transformation); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.ENCRYPT_MODE, key, iv); + c.updateAAD(aad); + c.doFinal(input, 0, input.length, tag_orig, 0); + } + + { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.ENCRYPT_MODE, key, iv); + c.updateAAD(aad); + c.doFinal(input, 0, input.length, tag, 0); + c.close(); + } + + // tag should be the same as JDK's cipher + Assert.assertArrayEquals(tag_orig, tag); + + // like JDK's decrypt mode. The plaintext+tag is the input for decrypt mode + // let's verify the add & tag now + { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.DECRYPT_MODE, key, iv); + c.updateAAD(aad); + c.doFinal(tag, 0, tag.length, input, 0); + c.close(); + } + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + @Test(expected = AEADBadTagException.class) + public void testGMacTamperedData() throws Exception { + Random r = new Random(); + byte[] keyBytes = new byte[32]; + byte[] input = new byte[0]; + byte[] ivBytes = new byte[16]; + + byte[] tag = new byte[16]; + + byte[] aad = new byte[r.nextInt() % 1000 + 1000 ]; + + r.nextBytes(keyBytes); + r.nextBytes(input); + r.nextBytes(ivBytes); + r.nextBytes(aad); + + try { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.ENCRYPT_MODE, key, iv); + c.updateAAD(aad); + c.doFinal(input, 0, input.length, tag, 0); + c.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + + try { + // like JDK's decrypt mode. The plaintext+tag is the input for decrypt mode + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.DECRYPT_MODE, key, iv); + + // if the origin data is tampered + aad[0] = (byte) (aad[0] + 1); + c.updateAAD(aad); + + c.doFinal(tag, 0, tag.length, input, 0); + c.close(); + + } + catch (AEADBadTagException ex) { + Assert.assertTrue("Tag mismatch!".equals(ex.getMessage())); + throw ex; + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + private void testGcmEncryption(String kHex, String pHex, String ivHex, String aadHex, + String cHex, String tHex){ + + byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex); + byte[] input = DatatypeConverter.parseHexBinary(pHex); + byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex); + byte[] aad = DatatypeConverter.parseHexBinary(aadHex); + byte[] expectedOutput = DatatypeConverter.parseHexBinary(cHex+tHex); + + byte[] output = new byte[expectedOutput.length]; + + try { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + + Key key = new SecretKeySpec(keyBytes, "AES"); + + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.ENCRYPT_MODE, key, iv); + c.updateAAD(aad); + + c.doFinal(input, 0, input.length, output, 0); + + Assert.assertArrayEquals(expectedOutput, output); + c.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + private void testGcmArbitraryLengthUpdate(String kHex, String pHex, String ivHex, String aadHex, + String cHex, String tHex){ + + byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex); + byte[] input = DatatypeConverter.parseHexBinary(pHex); + byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex); + byte[] aad = DatatypeConverter.parseHexBinary(aadHex); + byte[] expectedOutput = DatatypeConverter.parseHexBinary(cHex+tHex); + + byte[] encOutput = new byte[expectedOutput.length]; + byte[] decOutput = new byte[input.length]; + + try { + Random r = new Random(); + + CryptoCipher enc = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + enc.init(Cipher.ENCRYPT_MODE, key, iv); + if (aad.length > 0) { + int len1 = r.nextInt(aad.length) ; + byte[] aad1 = Arrays.copyOfRange(aad, 0, len1); + byte[] aad2 = Arrays.copyOfRange(aad, len1, aad.length); + enc.updateAAD(aad1); + enc.updateAAD(aad2); + } + + int partLen = r.nextInt(input.length); + int len = enc.update(input, 0, partLen, encOutput, 0); + Assert.assertTrue(len == partLen); + len = enc.doFinal(input, partLen, input.length - partLen, encOutput, partLen); + Assert.assertTrue(len == (input.length + (iv.getTLen() >> 3) - partLen)); + + Assert.assertArrayEquals(expectedOutput, encOutput); + enc.close(); + + // Decryption + CryptoCipher dec = Utils.getCipherInstance(transformation, props); + dec.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), + new GCMParameterSpec(128, ivBytes)); + if (aad.length > 0) { + int len1 = r.nextInt(aad.length) ; + byte[] aad1 = Arrays.copyOfRange(aad, 0, len1); + byte[] aad2 = Arrays.copyOfRange(aad, len1, aad.length); + dec.updateAAD(aad1); + dec.updateAAD(aad2); + } + byte[] decInput = encOutput; + partLen = r.nextInt(input.length); + len = dec.update(decInput, 0, partLen, decOutput, 0); + Assert.assertTrue(len == 0); + len = dec.doFinal(decInput, partLen, decInput.length - partLen, decOutput, 0); + Assert.assertTrue(len == input.length); + + Assert.assertArrayEquals(input, decOutput); + dec.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + private void testGcmDecryption(String kHex, String pHex, String ivHex, String aadHex, + String cHex, String tHex){ + + byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex); + byte[] plainBytes = DatatypeConverter.parseHexBinary(pHex); + byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex); + + byte[] aad = DatatypeConverter.parseHexBinary(aadHex); + byte[] cipherBytes = DatatypeConverter.parseHexBinary(cHex+tHex); + + byte[] input = cipherBytes; + byte[] output = new byte[plainBytes.length]; + + try { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + + Key key = new SecretKeySpec(keyBytes, "AES"); + + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.DECRYPT_MODE, key, iv); + c.updateAAD(aad); + c.doFinal(input, 0, input.length, output, 0); + + Assert.assertArrayEquals(plainBytes, output); + c.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + private void testGcmReturnDataAfterTagVerified(String kHex, String pHex, String ivHex, String aadHex, + String cHex, String tHex){ + + byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex); + byte[] plainBytes = DatatypeConverter.parseHexBinary(pHex); + byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex); + + byte[] aad = DatatypeConverter.parseHexBinary(aadHex); + byte[] cipherBytes = DatatypeConverter.parseHexBinary(cHex+tHex); + + byte[] input = cipherBytes; + byte[] output = new byte[plainBytes.length]; + + try { + CryptoCipher c = Utils.getCipherInstance(transformation, props); + + Key key = new SecretKeySpec(keyBytes, "AES"); + + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.DECRYPT_MODE, key, iv); + c.updateAAD(aad); + + //only return recovered data after tag is successfully verified + int len = c.update(input, 0, input.length, output, 0); + Assert.assertTrue(len == 0); + len += c.doFinal(input, input.length, 0, output, 0); + Assert.assertTrue(len == plainBytes.length); + + Assert.assertArrayEquals(plainBytes, output); + c.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + private void testGcmByteBuffer(String kHex, String pHex, String ivHex, String aadHex, + String cHex, String tHex){ + + byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex); + byte[] plainText = DatatypeConverter.parseHexBinary(pHex); + byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex); + byte[] aad = DatatypeConverter.parseHexBinary(aadHex); + byte[] cipherText = DatatypeConverter.parseHexBinary(cHex+tHex); + + byte[] encOutput = new byte[cipherText.length]; + byte[] decOutput = new byte[plainText.length]; + + try { + + ByteBuffer bfAAD = ByteBuffer.allocateDirect(aad.length); + bfAAD.put(aad); + + ByteBuffer bfPlainText; + ByteBuffer bfCipherText; + bfPlainText = ByteBuffer.allocateDirect(plainText.length); + bfCipherText = ByteBuffer.allocateDirect(encOutput.length); + + // Encryption ------------------- + CryptoCipher c = Utils.getCipherInstance(transformation, props); + Key key = new SecretKeySpec(keyBytes, "AES"); + GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes); + c.init(Cipher.ENCRYPT_MODE, key, iv); + + bfAAD.flip(); + c.updateAAD(bfAAD); + + bfPlainText.put(plainText); + bfPlainText.flip(); + bfCipherText.position(0); + + c.doFinal(bfPlainText, bfCipherText); + + bfCipherText.flip(); + bfCipherText.get(encOutput); + Assert.assertArrayEquals(cipherText, encOutput); + c.close(); + + // Decryption ------------------- + CryptoCipher dec = Utils.getCipherInstance(transformation, props); + dec.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), + new GCMParameterSpec(128, ivBytes)); + bfAAD.flip(); + dec.updateAAD(bfAAD); + bfCipherText.clear(); + bfPlainText.clear(); + bfCipherText.put(cipherText); + bfCipherText.flip(); + dec.doFinal(bfCipherText, bfPlainText); + bfPlainText.flip(); + bfPlainText.get(decOutput); + Assert.assertArrayEquals(plainText, decOutput); + dec.close(); + } + catch (Exception ex) { + Assert.fail(ex.getMessage()); + } + } + + private void initTestData() { + + int casesNumber = 4; + + kHex = new String[casesNumber]; + pHex = new String[casesNumber]; + ivHex = new String[casesNumber]; + aadHex = new String[casesNumber]; + cHex = new String[casesNumber]; + tHex = new String[casesNumber]; + + // http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf + // http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + // NIST Case2 ----------------------------- + // key length: 16 bytes + // plain text length: 16 bytes + // iv length: 12 bytes + // aad length: 0 bytes + kHex[0] = "00000000000000000000000000000000"; + pHex[0] = "00000000000000000000000000000000"; + ivHex[0] = "000000000000000000000000"; + aadHex[0] = ""; + cHex[0] = "0388dace60b6a392f328c2b971b2fe78"; + tHex[0] = "ab6e47d42cec13bdf53a67b21257bddf"; + + // NIST Case4 --------------------------------- + // key length: 16 bytes + // plain text length: 60 bytes + // iv length: 12 bytes + // aad length: 20 bytes + kHex[1] = "feffe9928665731c6d6a8f9467308308"; + pHex[1] = "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39"; + ivHex[1] = "cafebabefacedbaddecaf888"; + aadHex[1] = "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2"; + cHex[1] = "42831ec2217774244b7221b784d0d49c" + + "e3aa212f2c02a4e035c17e2329aca12e" + + "21d514b25466931c7d8f6a5aac84aa05" + + "1ba30b396a0aac973d58e091"; + tHex[1] = "5bc94fbc3221a5db94fae95ae7121a47"; + + // NIST Case5 --------------------------------- + // key length: 16 bytes + // plain text length: 60 bytes + // iv length: 8 bytes + // aad length: 20 bytes + kHex[2] = "feffe9928665731c6d6a8f9467308308"; + pHex[2] = "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39"; + ivHex[2] ="cafebabefacedbad"; // 64bits < 96bits + aadHex[2]="feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2"; + cHex[2] = "61353b4c2806934a777ff51fa22a4755" + + "699b2a714fcdc6f83766e5f97b6c7423" + + "73806900e49f24b22b097544d4896b42" + + "4989b5e1ebac0f07c23f4598"; + tHex[2] = "3612d2e79e3b0785561be14aaca2fccb"; + + // NIST Case6 --------------------------------- + // key length: 16 bytes + // plain text length: 60 bytes + // iv length: 60 bytes + // aad length: 20 bytes + kHex[3] = "feffe9928665731c6d6a8f9467308308"; + pHex[3] = "d9313225f88406e5a55909c5aff5269a" + + "86a7a9531534f7da2e4c303d8a318a72" + + "1c3c0c95956809532fcf0e2449a6b525" + + "b16aedf5aa0de657ba637b39"; + ivHex[3] = "9313225df88406e555909c5aff5269aa" + + "6a7a9538534f7da1e4c303d2a318a728" + + "c3c0c95156809539fcf0e2429a6b5254" + + "16aedbf5a0de6a57a637b39b"; // > 96bits + aadHex[3] = "feedfacedeadbeeffeedfacedeadbeef" + + "abaddad2"; + cHex[3] = "8ce24998625615b603a033aca13fb894" + + "be9112a5c3a211a8ba262a3cca7e2ca7" + + "01e4a9a4fba43c90ccdcb281d48c7c6f" + + "d62875d2aca417034c34aee5"; + tHex[3] = "619cc5aefffe0bfa462af43c1699d050"; + } +}