2 // SymmetricKeyWrap.cs - Implements symmetric key wrap algorithms
5 // Tim Coleman (tim@timcoleman.com)
7 // Copyright (C) Tim Coleman, 2004
13 using System.Security.Cryptography;
15 namespace System.Security.Cryptography.Xml {
17 internal class SymmetricKeyWrap {
19 public SymmetricKeyWrap ()
23 public static byte[] AESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData)
25 SymmetricAlgorithm symAlg = SymmetricAlgorithm.Create ("Rijndael");
27 // Apparently no one felt the need to document that this requires Electronic Codebook mode.
28 symAlg.Mode = CipherMode.ECB;
30 // This was also not documented anywhere.
31 symAlg.IV = new byte [16] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
33 ICryptoTransform transform = symAlg.CreateEncryptor (rgbKey, symAlg.IV);
35 int N = rgbWrappedKeyData.Length / 8;
37 byte[] B = new Byte [16];
38 byte [] C = new byte [8 * (N + 1)];
41 // B = AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
45 A = new byte [8] {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
46 transform.TransformBlock (Concatenate (A, rgbWrappedKeyData), 0, 16, B, 0);
47 Buffer.BlockCopy (MSB(B), 0, C, 0, 8);
48 Buffer.BlockCopy (LSB(B), 0, C, 8, 8);
50 // if N > 1, perform the following steps:
51 // 2. Initialize variables:
52 // Set A to 0xA6A6A6A6A6A6A6A6
55 A = new byte [8] {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
57 byte[][] R = new byte [N + 1][];
58 for (int i = 1; i <= N; i += 1) {
60 Buffer.BlockCopy (rgbWrappedKeyData, 8 * (i - 1), R [i], 0, 8);
63 // 3. Calculate intermediate values:
67 // B = AES(K)enc(A|R(i))
71 for (int j = 0; j <= 5; j += 1) {
72 for (int i = 1; i <= N; i += 1) {
73 transform.TransformBlock (Concatenate (A, R [i]), 0, 16, B, 0);
75 // Yawn. It was nice of those at NIST to document how exactly we should XOR
76 // an integer value with a byte array. Not.
77 byte[] T = BitConverter.GetBytes ((long) (N * j + i));
80 if (BitConverter.IsLittleEndian)
88 // 4. Output the results:
92 Buffer.BlockCopy (A, 0, C, 0, 8);
93 for (int i = 1; i <= N; i += 1)
94 Buffer.BlockCopy (R [i], 0, C, 8 * i, 8);
100 public static byte[] AESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
102 throw new NotImplementedException ();
106 public static byte[] TripleDESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData)
108 throw new NotImplementedException ();
112 public static byte[] TripleDESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
114 throw new NotImplementedException ();
117 private static byte[] Transform (byte[] data, ICryptoTransform t, bool flush)
119 MemoryStream output = new MemoryStream ();
120 CryptoStream crypto = new CryptoStream (output, t, CryptoStreamMode.Write);
121 crypto.Write (data, 0, data.Length);
128 buf = output.ToArray ();
130 buf = output.ToArray ();
138 private static byte[] ComputeCMSKeyChecksum (byte[] data)
140 byte[] hash = HashAlgorithm.Create ("SHA1").ComputeHash (data);
141 byte[] output = new byte [8];
143 Buffer.BlockCopy (hash, 0, output, 0, 8);
148 private static byte[] Concatenate (byte[] buf1, byte[] buf2)
150 byte[] output = new byte [buf1.Length + buf2.Length];
151 Buffer.BlockCopy (buf1, 0, output, 0, buf1.Length);
152 Buffer.BlockCopy (buf2, 0, output, buf1.Length, buf2.Length);
156 private static byte[] MSB (byte[] input)
158 byte[] output = new byte [8];
159 Buffer.BlockCopy (input, 0, output, 0, 8);
163 private static byte[] LSB (byte[] input)
165 byte[] output = new byte [8];
166 Buffer.BlockCopy (input, 8, output, 0, 8);
170 private static byte[] Xor (byte[] x, byte[] y)
172 // This should *not* happen.
173 if (x.Length != y.Length)
174 throw new CryptographicException ("Error performing Xor: arrays different length.");
176 byte[] output = new byte [x.Length];
177 for (int i = 0; i < x.Length; i += 1)
178 output [i] = (byte) (x [i] ^ y [i]);