/// <summary> /// Initializes a new instance of the <see cref="KeyWrapSalt"/> class. /// </summary> /// <param name="length">The salt. It must be a valid AES key length.</param> public KeyWrapSalt(byte[] salt) { if (salt == null) { throw new ArgumentNullException("salt"); } if (salt.Length != 0 && !AesKey.IsValidKeyLength(salt.Length)) { throw new InternalErrorException("A key wrap salt length must at least be equal to a valid AES key length."); } _salt = (byte[])salt.Clone(); }
/// <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> /// Initializes a new instance of the <see cref="Passphrase"/> class. /// </summary> /// <param name="passphrase">The passphrase.</param> public Passphrase(string passphrase) { if (passphrase == null) { throw new ArgumentNullException("passphrase"); } HashAlgorithm hashAlgorithm = new SHA1Managed(); byte[] ansiBytes = Encoding.GetEncoding(1252).GetBytes(passphrase); byte[] hash = hashAlgorithm.ComputeHash(ansiBytes); byte[] derivedPassphrase = new byte[16]; Array.Copy(hash, derivedPassphrase, derivedPassphrase.Length); _derivedPassphrase = new AesKey(derivedPassphrase); }
/// <summary> /// Instantiate a thumb print /// </summary> /// <param name="key">The key to thumbprint.</param> /// <param name="salt">The salt to use.</param> public AesKeyThumbprint(AesKey key, KeyWrapSalt salt, long iterations) { if (key == null) { throw new ArgumentNullException("key"); } if (salt == null) { throw new ArgumentNullException("salt"); } KeyWrap keyWrap = new KeyWrap(key, salt, iterations, KeyWrapMode.Specification); byte[] wrap = keyWrap.Wrap(key); Initialize(wrap); }
/// <summary> /// Initializes a new instance of the <see cref="Subkey"/> class. Different data is encrypted using /// different variants of the master encryption key. /// </summary> /// <param name="masterKey">The master key.</param> /// <param name="headerSubkey">The header subkey.</param> public Subkey(AesKey masterKey, HeaderSubkey headerSubkey) { if (masterKey == null) { throw new ArgumentNullException("masterKey"); } byte[] block = new byte[16]; byte subKeyValue; switch (headerSubkey) { case HeaderSubkey.Hmac: subKeyValue = 0; break; case HeaderSubkey.Validator: subKeyValue = 1; break; case HeaderSubkey.Headers: subKeyValue = 2; break; case HeaderSubkey.Data: subKeyValue = 3; break; default: throw new InternalErrorException("headerSubkey"); } block[0] = subKeyValue; using (AesCrypto aesCrypto = new AesCrypto(masterKey)) { _subKey = new AesKey(aesCrypto.Encrypt(block)); } }
/// <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; }
/// <summary> /// Create a KeyWrap instance for wrapping or unwrapping /// </summary> /// <param name="key">The key wrapping key</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, long iterations, KeyWrapMode mode) : this(key, KeyWrapSalt.Zero, iterations, mode) { }
/// <summary> /// Instantiate an AES transform with zero IV, CBC and no padding. /// </summary> /// <param name="key">The key</param> public AesCrypto(AesKey key) : this(key, AesIV.Zero, CipherMode.CBC, PaddingMode.None) { }