private static readonly byte[] DefaultIV = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; // http://www.ietf.org/rfc/rfc3394.txt (see 2.2.3) public static byte[] Wrap(byte[] cek, byte[] kek) { Ensure.MinBitSize(cek, 128, "AesKeyWrap.Wrap() expects content length not less than 128 bits, but was {0}", cek.Length * 8); Ensure.Divisible(cek.Length, 8, "AesKeyWrap.Wrap() expects content length to be divisable by 8, but was given a content of {0} bit size.", cek.Length * 8); // 1) Initialize variables byte[] a = DefaultIV; // Set A = IV, an initial value byte[][] r = Arrays.Slice(cek, 8); // For i = 1 to n // R[0][i] = P[i] long n = r.Length; // 2) Calculate intermediate values. for (long j = 0; j < 6; j++) // For j = 0 to 5 { for (long i = 0; i < n; i++) // For i=1 to n { long t = n * j + i + 1; byte[] b = AesEnc(kek, Arrays.Concat(a, r[i])); // B=AES(K, A | R[i]) a = Arrays.FirstHalf(b); // A=MSB(64,B) ^ t where t = (n*j)+i r[i] = Arrays.SecondHalf(b); // R[i] = LSB(64, B) a = Arrays.Xor(a, t); } } // 3) Output the results byte[][] c = new byte[n + 1][]; c[0] = a; // Set C[0] = A for (long i = 1; i <= n; i++) // For i = 1 to n { c[i] = r[i - 1]; // C[i] = R[i] } return(Arrays.Concat(c)); }
public static byte[] Wrap(byte[] cek, byte[] kek) { Ensure.MinBitSize(cek, 128, "AesKeyWrap.Wrap() expects content length not less than 128 bits, but was {0}", new object[] { (int)cek.Length * 8 }); Ensure.Divisible((int)cek.Length, 8, "AesKeyWrap.Wrap() expects content length to be divisable by 8, but was given a content of {0} bit size.", new object[] { (int)cek.Length * 8 }); byte[] defaultIV = AesKeyWrap.DefaultIV; byte[][] numArray = Arrays.Slice(cek, 8); long length = (long)((int)numArray.Length); for (long i = (long)0; i < (long)6; i += (long)1) { for (long j = (long)0; j < length; j += (long)1) { long num = length * i + j + (long)1; byte[] numArray1 = AesKeyWrap.AesEnc(kek, Arrays.Concat(new byte[][] { defaultIV, numArray[checked (j)] })); defaultIV = Arrays.FirstHalf(numArray1); numArray[checked (j)] = Arrays.SecondHalf(numArray1); defaultIV = Arrays.Xor(defaultIV, num); } } byte[][] numArray2 = new byte[checked (length + 1)][]; numArray2[0] = defaultIV; for (long k = (long)1; k <= length; k += (long)1) { numArray2[checked (k)] = numArray[checked (k - (long)1)]; } return(Arrays.Concat(numArray2)); }
public static byte[] Unwrap(byte[] encryptedCek, byte[] kek) { Ensure.MinBitSize(encryptedCek, 128, "AesKeyWrap.Unwrap() expects content length not less than 128 bits, but was {0}", new object[] { (int)encryptedCek.Length * 8 }); Ensure.Divisible((int)encryptedCek.Length, 8, "AesKeyWrap.Unwrap() expects content length to be divisable by 8, but was given a content of {0} bit size.", new object[] { (int)encryptedCek.Length * 8 }); byte[][] numArray = Arrays.Slice(encryptedCek, 8); byte[] numArray1 = numArray[0]; byte[][] numArray2 = new byte[(int)numArray.Length - 1][]; for (int i = 1; i < (int)numArray.Length; i++) { numArray2[i - 1] = numArray[i]; } long length = (long)((int)numArray2.Length); for (long j = (long)5; j >= (long)0; j -= (long)1) { for (long k = length - (long)1; k >= (long)0; k -= (long)1) { long num = length * j + k + (long)1; numArray1 = Arrays.Xor(numArray1, num); byte[] numArray3 = AesKeyWrap.AesDec(kek, Arrays.Concat(new byte[][] { numArray1, numArray2[checked (k)] })); numArray1 = Arrays.FirstHalf(numArray3); numArray2[checked (k)] = Arrays.SecondHalf(numArray3); } } if (!Arrays.ConstantTimeEquals(AesKeyWrap.DefaultIV, numArray1)) { throw new IntegrityException("AesKeyWrap integrity check failed."); } return(Arrays.Concat(numArray2)); }
public byte[][] Encrypt(byte[] aad, byte[] plainText, byte[] cek) { byte[] array; Ensure.BitSize(cek, this.keyLength, string.Format("AES-CBC with HMAC algorithm expected key of size {0} bits, but was given {1} bits", this.keyLength, (int)cek.Length * 8), new object[0]); byte[] numArray = Arrays.FirstHalf(cek); byte[] numArray1 = Arrays.SecondHalf(cek); byte[] numArray2 = Arrays.Random(128); try { using (Aes ae = Aes.Create()) { ae.Key = numArray1; ae.IV = numArray2; using (MemoryStream memoryStream = new MemoryStream()) { using (ICryptoTransform cryptoTransform = ae.CreateEncryptor(ae.Key, ae.IV)) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write)) { cryptoStream.Write(plainText, 0, (int)plainText.Length); cryptoStream.FlushFinalBlock(); array = memoryStream.ToArray(); } } } } } catch (CryptographicException cryptographicException) { throw new EncryptionException("Unable to encrypt content.", cryptographicException); } byte[] numArray3 = this.ComputeAuthTag(aad, numArray2, array, numArray); return(new byte[][] { numArray2, array, numArray3 }); }
public byte[] Decrypt(byte[] aad, byte[] cek, byte[] iv, byte[] cipherText, byte[] authTag) { Ensure.BitSize(cek, keyLength, string.Format("AES-CBC with HMAC algorithm expected key of size {0} bits, but was given {1} bits", keyLength, cek.Length * 8L)); byte[] hmacKey = Arrays.FirstHalf(cek); byte[] aesKey = Arrays.SecondHalf(cek); // Check MAC byte[] expectedAuthTag = ComputeAuthTag(aad, iv, cipherText, hmacKey); if (!Arrays.ConstantTimeEquals(expectedAuthTag, authTag)) { throw new IntegrityException("Authentication tag do not match."); } try { using (Aes aes = Aes.Create()) { aes.Key = aesKey; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (MemoryStream ms = new MemoryStream()) { using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) { using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write)) { cs.Write(cipherText, 0, cipherText.Length); cs.FlushFinalBlock(); return(ms.ToArray()); } } } } } catch (CryptographicException e) { throw new EncryptionException("Unable to decrypt content", e); } }
public byte[][] Encrypt(byte[] aad, byte[] plainText, byte[] cek) { Ensure.BitSize(cek, keyLength, string.Format("AES-CBC with HMAC algorithm expected key of size {0} bits, but was given {1} bits", keyLength, cek.Length * 8L)); byte[] hmacKey = Arrays.FirstHalf(cek); byte[] aesKey = Arrays.SecondHalf(cek); byte[] iv = Arrays.Random(); byte[] cipherText; try { using (Aes aes = Aes.Create()) { aes.Key = aesKey; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (MemoryStream ms = new MemoryStream()) { using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV)) { using (CryptoStream encrypt = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { encrypt.Write(plainText, 0, plainText.Length); encrypt.FlushFinalBlock(); cipherText = ms.ToArray(); } } } } } catch (CryptographicException e) { throw new EncryptionException("Unable to encrypt content.", e); } byte[] authTag = ComputeAuthTag(aad, iv, cipherText, hmacKey); return(new[] { iv, cipherText, authTag }); }
public static byte[] Unwrap(byte[] encryptedCek, byte[] kek) { Ensure.MinBitSize(encryptedCek, 128, "AesKeyWrap.Unwrap() expects content length not less than 128 bits, but was {0}", encryptedCek.Length * 8); Ensure.Divisible(encryptedCek.Length, 8, "AesKeyWrap.Unwrap() expects content length to be divisable by 8, but was given a content of {0} bit size.", encryptedCek.Length * 8); // 1) Initialize variables byte[][] c = Arrays.Slice(encryptedCek, 8); byte[] a = c[0]; // Set A = C[0] byte[][] r = new byte[c.Length - 1][]; for (int i = 1; i < c.Length; i++) // For i = 1 to n { r[i - 1] = c[i]; // R[i] = C[i] } long n = r.Length; // 2) Calculate intermediate values for (long j = 5; j >= 0; j--) // For j = 5 to 0 { for (long i = n - 1; i >= 0; i--) // For i = n to 1 { long t = n * j + i + 1; a = Arrays.Xor(a, t); byte[] B = AesDec(kek, Arrays.Concat(a, r[i])); // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i a = Arrays.FirstHalf(B); // A = MSB(64, B) r[i] = Arrays.SecondHalf(B); // R[i] = LSB(64, B) } } // 3) Output the results if (!Arrays.ConstantTimeEquals(DefaultIV, a)) // If A is an appropriate initial value { throw new IntegrityException("AesKeyWrap integrity check failed."); } // For i = 1 to n return(Arrays.Concat(r)); // P[i] = R[i] }
public byte[] Decrypt(byte[] aad, byte[] cek, byte[] iv, byte[] cipherText, byte[] authTag) { byte[] array; Ensure.BitSize(cek, this.keyLength, string.Format("AES-CBC with HMAC algorithm expected key of size {0} bits, but was given {1} bits", this.keyLength, (int)cek.Length * 8), new object[0]); byte[] numArray = Arrays.FirstHalf(cek); byte[] numArray1 = Arrays.SecondHalf(cek); if (!Arrays.ConstantTimeEquals(this.ComputeAuthTag(aad, iv, cipherText, numArray), authTag)) { throw new IntegrityException("Authentication tag do not match."); } try { using (Aes ae = Aes.Create()) { ae.Key = numArray1; ae.IV = iv; using (MemoryStream memoryStream = new MemoryStream()) { using (ICryptoTransform cryptoTransform = ae.CreateDecryptor(ae.Key, ae.IV)) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write)) { cryptoStream.Write(cipherText, 0, (int)cipherText.Length); cryptoStream.FlushFinalBlock(); array = memoryStream.ToArray(); } } } } } catch (CryptographicException cryptographicException) { throw new EncryptionException("Unable to decrypt content", cryptographicException); } return(array); }