コード例 #1
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(ICrypto crypto, byte[] wrapped)
        {
            if (wrapped == null)
            {
                throw new ArgumentNullException("wrapped");
            }

            if (crypto == null)
            {
                throw new ArgumentNullException("crypto");
            }
            if (wrapped.Length % (crypto.BlockLength / 2) != 0)
            {
                throw new InternalErrorException("The length of the wrapped data must a multiple of half the algorithm block size.");
            }
            if (wrapped.Length < 24)
            {
                throw new InternalErrorException("The length of the wrapped data must be large enough to accommodate at least a 128-bit key.");
            }

            using (IKeyWrapTransform decryptor = crypto.CreateKeyWrapTransform(_salt, KeyWrapDirection.Decrypt))
            {
                return(UnwrapInternal(wrapped, decryptor));
            }
        }
コード例 #2
0
        private byte[] UnwrapInternal(byte[] wrapped, IKeyWrapTransform decryptor)
        {
            byte[] a = decryptor.A();
            int    halfBlockLength  = decryptor.BlockLength / 2;
            int    wrappedKeyLength = wrapped.Length - a.Length;

            wrapped = (byte[])wrapped.Clone();

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

            // 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 = _keyWrapIterations - 1; j >= 0; --j)
            {
                for (int i = wrappedKeyLength / halfBlockLength; i >= 1; --i)
                {
                    long t = ((wrappedKeyLength / halfBlockLength) * j) + i;
                    // MSB(B) = A XOR t
                    Array.Copy(wrapped, 0, block, 0, halfBlockLength);
                    switch (_mode)
                    {
                    case KeyWrapMode.Specification:
                        block.Xor(0, t.GetBigEndianBytes(), 0, halfBlockLength);
                        break;

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

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

            byte[] unwrapped = new byte[wrapped.Length - a.Length];
            Array.Copy(wrapped, a.Length, unwrapped, 0, wrapped.Length - a.Length);
            return(unwrapped);
        }
コード例 #3
0
        public byte[] Wrap(ICrypto crypto, byte[] keyMaterial)
        {
            if (crypto == null)
            {
                throw new ArgumentNullException("crypto");
            }
            if (keyMaterial == null)
            {
                throw new ArgumentNullException("keyMaterial");
            }

            using (IKeyWrapTransform encryptor = crypto.CreateKeyWrapTransform(_salt, KeyWrapDirection.Encrypt))
            {
                return(WrapInternal(keyMaterial, encryptor));
            }
        }
コード例 #4
0
        private byte[] WrapInternal(byte[] keyMaterial, IKeyWrapTransform encryptor)
        {
            byte[] a = encryptor.A();

            byte[] wrapped = new byte[keyMaterial.Length + a.Length];
            a.CopyTo(wrapped, 0);

            Array.Copy(keyMaterial, 0, wrapped, a.Length, keyMaterial.Length);

            byte[] block           = new byte[encryptor.BlockLength];
            int    halfBlockLength = encryptor.BlockLength / 2;

            // wrapped[0..halfBlockLength-1] 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 < _keyWrapIterations; j++)
            {
                for (int i = 1; i <= keyMaterial.Length / halfBlockLength; i++)
                {
                    // B = AESE(K, A | R[i])
                    Array.Copy(wrapped, 0, block, 0, halfBlockLength);
                    Array.Copy(wrapped, i * halfBlockLength, block, halfBlockLength, halfBlockLength);
                    byte[] b = encryptor.TransformBlock(block);
                    // A = MSB64(B) XOR t where t = (n * j) + i
                    long t = ((keyMaterial.Length / halfBlockLength) * j) + i;
                    switch (_mode)
                    {
                    case KeyWrapMode.Specification:
                        b.Xor(0, t.GetBigEndianBytes(), 0, halfBlockLength);
                        break;

                    case KeyWrapMode.AxCrypt:
                        b.Xor(0, t.GetLittleEndianBytes(), 0, halfBlockLength);
                        break;
                    }
                    Array.Copy(b, 0, wrapped, 0, halfBlockLength);
                    // R[i] = LSB64(B)
                    Array.Copy(b, halfBlockLength, wrapped, i * halfBlockLength, halfBlockLength);
                }
            }
            return(wrapped);
        }