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); }
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); }