SymmetricKeyWrap.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // SymmetricKeyWrap.cs - Implements symmetric key wrap algorithms
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. //
  7. // Copyright (C) Tim Coleman, 2004
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. #if NET_2_0
  30. using System.IO;
  31. using System.Security.Cryptography;
  32. namespace System.Security.Cryptography.Xml {
  33. internal class SymmetricKeyWrap {
  34. public SymmetricKeyWrap ()
  35. {
  36. }
  37. public static byte[] AESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData)
  38. {
  39. SymmetricAlgorithm symAlg = SymmetricAlgorithm.Create ("Rijndael");
  40. // Apparently no one felt the need to document that this requires Electronic Codebook mode.
  41. symAlg.Mode = CipherMode.ECB;
  42. // This was also not documented anywhere.
  43. symAlg.IV = new byte [16] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  44. ICryptoTransform transform = symAlg.CreateEncryptor (rgbKey, symAlg.IV);
  45. int N = rgbWrappedKeyData.Length / 8;
  46. byte[] A;
  47. byte[] B = new Byte [16];
  48. byte [] C = new byte [8 * (N + 1)];
  49. // 1. if N is 1:
  50. // B = AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
  51. // C(0) = MSB(B)
  52. // C(1) = LSB(B)
  53. if (N == 1) {
  54. A = new byte [8] {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
  55. transform.TransformBlock (Concatenate (A, rgbWrappedKeyData), 0, 16, B, 0);
  56. Buffer.BlockCopy (MSB(B), 0, C, 0, 8);
  57. Buffer.BlockCopy (LSB(B), 0, C, 8, 8);
  58. } else {
  59. // if N > 1, perform the following steps:
  60. // 2. Initialize variables:
  61. // Set A to 0xA6A6A6A6A6A6A6A6
  62. // For i = 1 to N,
  63. // R(i) = P(i)
  64. A = new byte [8] {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
  65. byte[][] R = new byte [N + 1][];
  66. for (int i = 1; i <= N; i += 1) {
  67. R [i] = new byte [8];
  68. Buffer.BlockCopy (rgbWrappedKeyData, 8 * (i - 1), R [i], 0, 8);
  69. }
  70. // 3. Calculate intermediate values:
  71. // For j = 0 to 5
  72. // For i = 1 to N
  73. // t = i + j * N
  74. // B = AES(K)enc(A|R(i))
  75. // A = XOR(t, MSB(B))
  76. // R(i) = LSB(B)
  77. for (int j = 0; j <= 5; j += 1) {
  78. for (int i = 1; i <= N; i += 1) {
  79. transform.TransformBlock (Concatenate (A, R [i]), 0, 16, B, 0);
  80. // Yawn. It was nice of those at NIST to document how exactly we should XOR
  81. // an integer value with a byte array. Not.
  82. byte[] T = BitConverter.GetBytes ((long) (N * j + i));
  83. // This is nice.
  84. if (BitConverter.IsLittleEndian)
  85. Array.Reverse (T);
  86. A = Xor (T, MSB(B));
  87. R [i] = LSB (B);
  88. }
  89. }
  90. // 4. Output the results:
  91. // Set C(0) = A
  92. // For i = 1 to N
  93. // C(i) = R(i)
  94. Buffer.BlockCopy (A, 0, C, 0, 8);
  95. for (int i = 1; i <= N; i += 1)
  96. Buffer.BlockCopy (R [i], 0, C, 8 * i, 8);
  97. }
  98. return C;
  99. }
  100. [MonoTODO]
  101. public static byte[] AESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
  102. {
  103. throw new NotImplementedException ();
  104. }
  105. [MonoTODO]
  106. public static byte[] TripleDESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData)
  107. {
  108. throw new NotImplementedException ();
  109. }
  110. [MonoTODO]
  111. public static byte[] TripleDESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
  112. {
  113. throw new NotImplementedException ();
  114. }
  115. private static byte[] Transform (byte[] data, ICryptoTransform t, bool flush)
  116. {
  117. MemoryStream output = new MemoryStream ();
  118. CryptoStream crypto = new CryptoStream (output, t, CryptoStreamMode.Write);
  119. crypto.Write (data, 0, data.Length);
  120. byte[] buf;
  121. if (flush) {
  122. crypto.Close ();
  123. output.Close ();
  124. buf = output.ToArray ();
  125. } else {
  126. buf = output.ToArray ();
  127. crypto.Close ();
  128. output.Close ();
  129. }
  130. return buf;
  131. }
  132. private static byte[] ComputeCMSKeyChecksum (byte[] data)
  133. {
  134. byte[] hash = HashAlgorithm.Create ("SHA1").ComputeHash (data);
  135. byte[] output = new byte [8];
  136. Buffer.BlockCopy (hash, 0, output, 0, 8);
  137. return output;
  138. }
  139. private static byte[] Concatenate (byte[] buf1, byte[] buf2)
  140. {
  141. byte[] output = new byte [buf1.Length + buf2.Length];
  142. Buffer.BlockCopy (buf1, 0, output, 0, buf1.Length);
  143. Buffer.BlockCopy (buf2, 0, output, buf1.Length, buf2.Length);
  144. return output;
  145. }
  146. private static byte[] MSB (byte[] input)
  147. {
  148. byte[] output = new byte [8];
  149. Buffer.BlockCopy (input, 0, output, 0, 8);
  150. return output;
  151. }
  152. private static byte[] LSB (byte[] input)
  153. {
  154. byte[] output = new byte [8];
  155. Buffer.BlockCopy (input, 8, output, 0, 8);
  156. return output;
  157. }
  158. private static byte[] Xor (byte[] x, byte[] y)
  159. {
  160. // This should *not* happen.
  161. if (x.Length != y.Length)
  162. throw new CryptographicException ("Error performing Xor: arrays different length.");
  163. byte[] output = new byte [x.Length];
  164. for (int i = 0; i < x.Length; i += 1)
  165. output [i] = (byte) (x [i] ^ y [i]);
  166. return output;
  167. }
  168. }
  169. }
  170. #endif