Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="KeyWrapSalt"/> class.
 /// </summary>
 /// <param name="length">The length of the salt in bytes. It must be a valid AES key length.</param>
 public KeyWrapSalt(int length)
 {
     if (!AesKey.IsValidKeyLength(length))
     {
         throw new InternalErrorException("A key wrap salt length must at least be equal to a valid AES key length.");
     }
     _salt = OS.Current.GetRandomBytes(length);
 }
Esempio n. 2
0
        /// <summary>
        /// Unwrap an AES Key Wrapped-key
        /// </summary>
        /// <param name="wrapped">The full wrapped data, the length of a key + 8 bytes</param>
        /// <returns>The unwrapped key data, or a zero-length array if the unwrap was unsuccessful due to wrong key</returns>
        public byte[] Unwrap(byte[] wrapped)
        {
            if (_aes == null)
            {
                throw new ObjectDisposedException("_aes");
            }

            int wrappedKeyLength = wrapped.Length - A.Length;

            if (!AesKey.IsValidKeyLength(wrappedKeyLength))
            {
                throw new InternalErrorException("The length of the wrapped data must be exactly the length of a valid key length plus 8 bytes");
            }

            wrapped = (byte[])wrapped.Clone();
            ICryptoTransform decryptor = _aes.CreateDecryptor();

            byte[] block = new byte[decryptor.InputBlockSize];

            // wrapped[0..7] contains the A (IV) of the Key Wrap algorithm,
            // the rest is 'Wrapped Key Data', R[1], ..., R[n]. We do the transform in-place.
            for (long j = _iterations - 1; j >= 0; --j)
            {
                for (int i = wrappedKeyLength / 8; i >= 1; --i)
                {
                    long t = ((wrappedKeyLength / 8) * j) + i;
                    // MSB(B) = A XOR t
                    Array.Copy(wrapped, 0, block, 0, 8);
                    switch (_mode)
                    {
                    case KeyWrapMode.Specification:
                        block.Xor(0, t.GetBigEndianBytes(), 0, 8);
                        break;

                    case KeyWrapMode.AxCrypt:
                        block.Xor(0, t.GetLittleEndianBytes(), 0, 8);
                        break;
                    }
                    // LSB(B) = R[i]
                    Array.Copy(wrapped, i * 8, block, 8, 8);
                    // B = AESD(K, X xor t | R[i]) where t = (n * j) + i
                    byte[] b = decryptor.TransformFinalBlock(block, 0, decryptor.InputBlockSize);
                    // A = MSB(B)
                    Array.Copy(b, 0, wrapped, 0, 8);
                    // R[i] = LSB(B)
                    Array.Copy(b, 8, wrapped, i * 8, 8);
                }
            }

            if (!wrapped.IsEquivalentTo(0, A, 0, A.Length))
            {
                return(new byte[0]);
            }

            byte[] unwrapped = new byte[_key.Length];
            Array.Copy(wrapped, A.Length, unwrapped, 0, unwrapped.Length);
            return(unwrapped);
        }
Esempio n. 3
0
 /// <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();
 }