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)); }
private static byte[] F(byte[] salt, int iterationCount, int blockIndex, HMAC prf) { byte[] numArray = prf.ComputeHash(Arrays.Concat(new byte[][] { salt, Arrays.IntToBytes(blockIndex) })); byte[] numArray1 = numArray; for (int i = 2; i <= iterationCount; i++) { numArray = prf.ComputeHash(numArray); numArray1 = Arrays.Xor(numArray1, numArray); } return(numArray1); }
private static byte[] F(byte[] salt, int iterationCount, int blockIndex, HMAC prf) { byte[] U = prf.ComputeHash(Arrays.Concat(salt, Arrays.IntToBytes(blockIndex))); // U_1 = PRF (P, S || INT (i)) byte[] result = U; for (int i = 2; i <= iterationCount; i++) { U = prf.ComputeHash(U); // U_c = PRF (P, U_{c-1}) . result = Arrays.Xor(result, U); // U_1 \xor U_2 \xor ... \xor U_c } return(result); }
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] }