/// <summary> /// Decrypt in aes128-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96 /// </summary> /// <param name="key">key data</param> /// <param name="cipher">cipher data to be decrypted</param> /// <param name="usage">key usage number</param> /// <param name="aesKeyType">aes key type (128bit/256bit)</param> /// <param name="getToBeSignedDateCallback"> /// A callback to get to-be-signed data. /// The method will use decrypted data directly if this parameter is null. /// </param> /// <returns>the decrypted data</returns> public static byte[] Decrypt( byte[] key, byte[] cipher, int usage, AesKeyType aesKeyType, GetToBeSignedDataFunc getToBeSignedDateCallback) { // check inputs if (null == key) { throw new ArgumentNullException("key"); } if (null == cipher) { throw new ArgumentNullException("cipher"); } // the cipher has two parts: encrypted(confounder + plain) + hmac byte[] encryptedData = ArrayUtility.SubArray <byte>( cipher, 0, cipher.Length - ConstValue.HMAC_HASH_OUTPUT_SIZE); byte[] hmacData = ArrayUtility.SubArray <byte>( cipher, cipher.Length - ConstValue.HMAC_HASH_OUTPUT_SIZE); // use ke key (the encryption key) to decrypt byte[] ke = AesKey.MakeDerivedKey(key, usage, DerivedKeyType.Ke, aesKeyType); byte[] initialVector = new byte[ConstValue.AES_BLOCK_SIZE]; CipherTextStealingMode aesCtsCrypto = CryptoUtility.CreateAesCtsCrypto(ke, initialVector); byte[] decryptedData = aesCtsCrypto.DecryptFinal(encryptedData, 0, encryptedData.Length); byte[] toBeSignedData; if (getToBeSignedDateCallback != null) { toBeSignedData = getToBeSignedDateCallback(decryptedData); } else { toBeSignedData = decryptedData; } // use ki key (the integrity key) to verify hmac data byte[] ki = AesKey.MakeDerivedKey(key, usage, DerivedKeyType.Ki, aesKeyType); byte[] expectedHmacData = CryptoUtility.ComputeHmacSha1(ki, toBeSignedData); expectedHmacData = ArrayUtility.SubArray <byte>(expectedHmacData, 0, ConstValue.HMAC_HASH_OUTPUT_SIZE); if (!ArrayUtility.CompareArrays <byte>(hmacData, expectedHmacData)) { throw new FormatException( "Decryption: failed integrity check in hmac checksum."); } // remove confounder data decryptedData = ArrayUtility.SubArray <byte>(decryptedData, ConstValue.AES_BLOCK_SIZE, decryptedData.Length - ConstValue.AES_BLOCK_SIZE); return(decryptedData); }
/// <summary> /// Get Hmac-Sha1-Aes Checksum /// </summary> /// <param name="key">the key</param> /// <param name="input">input data</param> /// <param name="usage">usage number</param> /// <param name="aesKeyType">aes key type which decides key size</param> /// <returns>the calculated checksum</returns> public static byte[] GetMic( byte[] key, byte[] input, int usage, AesKeyType aesKeyType) { // make the kc key from aes key generation byte[] kcKey = AesKey.MakeDerivedKey( key, usage, DerivedKeyType.Kc, aesKeyType); // get mic from kc key and input byte[] hash = CryptoUtility.ComputeHmacSha1(kcKey, input); return(ArrayUtility.SubArray(hash, 0, ConstValue.HMAC_HASH_OUTPUT_SIZE)); }
/// <summary> /// Encrypt in aes128-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96 /// </summary> /// <param name="key">key data</param> /// <param name="plain">plain data to be encrypted</param> /// <param name="usage">key usage number</param> /// <param name="aesKeyType">aes key type (128bit/256bit)</param> /// <param name="getToBeSignedDateCallback"> /// A callback to get to-be-signed data. /// The method will use plain-text data directly if this parameter is null. /// </param> /// <returns>the encrypted data</returns> public static byte[] Encrypt( byte[] key, byte[] plain, int usage, AesKeyType aesKeyType, GetToBeSignedDataFunc getToBeSignedDateCallback) { // check inputs if (null == key) { throw new ArgumentNullException("key"); } if (null == plain) { throw new ArgumentNullException("plain"); } // add confounder data byte[] plainData = ArrayUtility.ConcatenateArrays( CryptoUtility.CreateConfounder(ConstValue.AES_BLOCK_SIZE), plain); // use ke key (the encryption key) to encrypt the plain data byte[] ke = AesKey.MakeDerivedKey(key, usage, DerivedKeyType.Ke, aesKeyType); byte[] initialVector = new byte[ConstValue.AES_BLOCK_SIZE]; CipherTextStealingMode aesCtsCrypto = CryptoUtility.CreateAesCtsCrypto(ke, initialVector); byte[] encryptedData = aesCtsCrypto.EncryptFinal(plainData, 0, plainData.Length); byte[] toBeSignedData; if (getToBeSignedDateCallback != null) { toBeSignedData = getToBeSignedDateCallback(plainData); } else { toBeSignedData = plainData; } // use ki key (the integrity key) to generate checksum byte[] ki = AesKey.MakeDerivedKey(key, usage, DerivedKeyType.Ki, aesKeyType); byte[] hmacData = CryptoUtility.ComputeHmacSha1(ki, toBeSignedData); hmacData = ArrayUtility.SubArray <byte>(hmacData, 0, ConstValue.HMAC_HASH_OUTPUT_SIZE); // result: encryptedData + hmacData return(ArrayUtility.ConcatenateArrays(encryptedData, hmacData)); }