/// <summary> /// Initializes a new instance of the AxCryptHMACSHA1 class /// with a provided key. /// </summary> /// <param name="key">The key</param> public static HMAC Create(AesKey key) { if (key == null) { throw new ArgumentNullException("key"); } AxCryptHMACSHA1 hmac = new AxCryptHMACSHA1(); hmac.BlockSizeValue = 20; hmac.Key = key.GetBytes(); return(hmac); }
/// <summary> /// Wrap key data using the AES Key Wrap specification /// </summary> /// <param name="keyToWrap">The key to wrap</param> /// <returns>The wrapped key data, 8 bytes longer than the key</returns> public byte[] Wrap(AesKey keyToWrap) { if (keyToWrap == null) { throw new ArgumentNullException("keyToWrap"); } if (_aes == null) { throw new ObjectDisposedException("_aes"); } byte[] wrapped = new byte[keyToWrap.Length + A.Length]; A.CopyTo(wrapped, 0); Array.Copy(keyToWrap.GetBytes(), 0, wrapped, A.Length, keyToWrap.Length); ICryptoTransform encryptor = _aes.CreateEncryptor(); byte[] block = new byte[encryptor.InputBlockSize]; // wrapped[0..7] contains the A (IV) of the Key Wrap algorithm, // the rest is 'Key Data'. We do the transform in-place. for (int j = 0; j < _iterations; j++) { for (int i = 1; i <= keyToWrap.Length / 8; i++) { // B = AESE(K, A | R[i]) Array.Copy(wrapped, 0, block, 0, 8); Array.Copy(wrapped, i * 8, block, 8, 8); byte[] b = encryptor.TransformFinalBlock(block, 0, encryptor.InputBlockSize); // A = MSB64(B) XOR t where t = (n * j) + i long t = ((keyToWrap.Length / 8) * j) + i; switch (_mode) { case KeyWrapMode.Specification: b.Xor(0, t.GetBigEndianBytes(), 0, 8); break; case KeyWrapMode.AxCrypt: b.Xor(0, t.GetLittleEndianBytes(), 0, 8); break; } Array.Copy(b, 0, wrapped, 0, 8); // R[i] = LSB64(B) Array.Copy(b, 8, wrapped, i * 8, 8); } } return(wrapped); }
/// <summary> /// Instantiate a transformation /// </summary> /// <param name="key">The key</param> /// <param name="iv">Initial Vector</param> /// <param name="cipherMode">Mode of operation, typically CBC</param> /// <param name="paddingMode">Padding mode, typically PCS7</param> public AesCrypto(AesKey key, AesIV iv, CipherMode cipherMode, PaddingMode paddingMode) { if (key == null) { throw new ArgumentNullException("key"); } if (iv == null) { throw new ArgumentNullException("iv"); } _aes = new AesManaged(); _aes.Key = key.GetBytes(); _aes.Mode = cipherMode; _aes.IV = iv.GetBytes(); _aes.Padding = paddingMode; }
/// <summary> /// Create a KeyWrap instance for wrapping or unwrapping /// </summary> /// <param name="key">The key wrapping key</param> /// <param name="salt">An optional salt, or null if none. AxCrypt uses a salt.</param> /// <param name="iterations">The number of wrapping iterations, at least 6</param> /// <param name="mode">Use original specification mode or AxCrypt mode (only difference is that 't' is little endian in AxCrypt mode)</param> public KeyWrap(AesKey key, KeyWrapSalt salt, long iterations, KeyWrapMode mode) { if (key == null) { throw new ArgumentNullException("key"); } if (salt == null) { throw new ArgumentNullException("salt"); } if (salt.Length != 0 && salt.Length != key.Length) { throw new InternalErrorException("salt length is incorrect"); } if (iterations < 6) { throw new InternalErrorException("iterations"); } if (mode != KeyWrapMode.Specification && mode != KeyWrapMode.AxCrypt) { throw new InternalErrorException("mode"); } _mode = mode; _key = key; _salt = salt; _iterations = iterations; byte[] saltedKey = _key.GetBytes(); saltedKey.Xor(_salt.GetBytes()); _aes.Mode = CipherMode.ECB; _aes.KeySize = _key.Length * 8; _aes.Key = saltedKey; _aes.Padding = PaddingMode.None; }