2 // SymmetricKeyWrap.cs - Implements symmetric key wrap algorithms
5 // Tim Coleman (tim@timcoleman.com)
7 // Copyright (C) Tim Coleman, 2004
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Security.Cryptography;
36 namespace System.Security.Cryptography.Xml {
38 internal class SymmetricKeyWrap {
40 public SymmetricKeyWrap ()
44 public static byte[] AESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData)
46 SymmetricAlgorithm symAlg = SymmetricAlgorithm.Create ("Rijndael");
48 // Apparently no one felt the need to document that this requires Electronic Codebook mode.
49 symAlg.Mode = CipherMode.ECB;
51 // This was also not documented anywhere.
52 symAlg.IV = new byte [16] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
54 ICryptoTransform transform = symAlg.CreateEncryptor (rgbKey, symAlg.IV);
56 int N = rgbWrappedKeyData.Length / 8;
58 byte[] B = new Byte [16];
59 byte [] C = new byte [8 * (N + 1)];
62 // B = AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
66 A = new byte [8] {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
67 transform.TransformBlock (Concatenate (A, rgbWrappedKeyData), 0, 16, B, 0);
68 Buffer.BlockCopy (MSB(B), 0, C, 0, 8);
69 Buffer.BlockCopy (LSB(B), 0, C, 8, 8);
71 // if N > 1, perform the following steps:
72 // 2. Initialize variables:
73 // Set A to 0xA6A6A6A6A6A6A6A6
76 A = new byte [8] {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
78 byte[][] R = new byte [N + 1][];
79 for (int i = 1; i <= N; i += 1) {
81 Buffer.BlockCopy (rgbWrappedKeyData, 8 * (i - 1), R [i], 0, 8);
84 // 3. Calculate intermediate values:
88 // B = AES(K)enc(A|R(i))
92 for (int j = 0; j <= 5; j += 1) {
93 for (int i = 1; i <= N; i += 1) {
94 transform.TransformBlock (Concatenate (A, R [i]), 0, 16, B, 0);
96 // Yawn. It was nice of those at NIST to document how exactly we should XOR
97 // an integer value with a byte array. Not.
98 byte[] T = BitConverter.GetBytes ((long) (N * j + i));
101 if (BitConverter.IsLittleEndian)
109 // 4. Output the results:
113 Buffer.BlockCopy (A, 0, C, 0, 8);
114 for (int i = 1; i <= N; i += 1)
115 Buffer.BlockCopy (R [i], 0, C, 8 * i, 8);
121 public static byte[] AESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
123 throw new NotImplementedException ();
127 public static byte[] TripleDESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData)
129 throw new NotImplementedException ();
133 public static byte[] TripleDESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
135 throw new NotImplementedException ();
138 private static byte[] Transform (byte[] data, ICryptoTransform t, bool flush)
140 MemoryStream output = new MemoryStream ();
141 CryptoStream crypto = new CryptoStream (output, t, CryptoStreamMode.Write);
142 crypto.Write (data, 0, data.Length);
149 buf = output.ToArray ();
151 buf = output.ToArray ();
159 private static byte[] ComputeCMSKeyChecksum (byte[] data)
161 byte[] hash = HashAlgorithm.Create ("SHA1").ComputeHash (data);
162 byte[] output = new byte [8];
164 Buffer.BlockCopy (hash, 0, output, 0, 8);
169 private static byte[] Concatenate (byte[] buf1, byte[] buf2)
171 byte[] output = new byte [buf1.Length + buf2.Length];
172 Buffer.BlockCopy (buf1, 0, output, 0, buf1.Length);
173 Buffer.BlockCopy (buf2, 0, output, buf1.Length, buf2.Length);
177 private static byte[] MSB (byte[] input)
179 byte[] output = new byte [8];
180 Buffer.BlockCopy (input, 0, output, 0, 8);
184 private static byte[] LSB (byte[] input)
186 byte[] output = new byte [8];
187 Buffer.BlockCopy (input, 8, output, 0, 8);
191 private static byte[] Xor (byte[] x, byte[] y)
193 // This should *not* happen.
194 if (x.Length != y.Length)
195 throw new CryptographicException ("Error performing Xor: arrays different length.");
197 byte[] output = new byte [x.Length];
198 for (int i = 0; i < x.Length; i += 1)
199 output [i] = (byte) (x [i] ^ y [i]);