InMemorySymmetricSecurityKey.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // InMemorySymmetricSecurityKey.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // Copyright (C) 2006-2007 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Collections.Generic;
  30. using System.IO;
  31. using System.Xml;
  32. using System.IdentityModel.Policy;
  33. using System.Security.Cryptography;
  34. using System.Security.Cryptography.Xml;
  35. using M = Mono.Security.Cryptography;
  36. using AES = System.Security.Cryptography.RijndaelManaged;
  37. namespace System.IdentityModel.Tokens
  38. {
  39. public class InMemorySymmetricSecurityKey : SymmetricSecurityKey
  40. {
  41. byte [] key;
  42. public InMemorySymmetricSecurityKey (byte [] key)
  43. : this (key, true)
  44. {
  45. }
  46. public InMemorySymmetricSecurityKey (byte [] key, bool clone)
  47. {
  48. if (key == null)
  49. throw new ArgumentNullException ("key");
  50. this.key = clone ? (byte []) key.Clone() : key;
  51. }
  52. // SymmetricSecurityKey implementation
  53. public override byte [] GenerateDerivedKey (
  54. string algorithm, byte [] label, byte [] nonce,
  55. int derivedKeyLength, int offset)
  56. {
  57. if (derivedKeyLength < 0)
  58. throw new ArgumentOutOfRangeException ("derivedKeyLength");
  59. if (offset < 0)
  60. throw new ArgumentOutOfRangeException ("offset");
  61. if (label == null)
  62. throw new ArgumentNullException ("label");
  63. if (nonce == null)
  64. throw new ArgumentNullException ("nonce");
  65. if (algorithm != SecurityAlgorithms.Psha1KeyDerivation)
  66. throw new InvalidOperationException (String.Format ("Key derivation algorithm '{0}' is not supported", algorithm));
  67. byte [] seed = new byte [label.Length + nonce.Length];
  68. Array.Copy (label, seed, label.Length);
  69. Array.Copy (nonce, 0, seed, label.Length, nonce.Length);
  70. byte [] p_sha = Expand ("SHA1", key, seed, derivedKeyLength / 8);
  71. return p_sha;
  72. }
  73. // from Mono.Security.Protocol.Tls.CipherSuite.Expand() with
  74. // a bit of modification ...
  75. byte [] Expand (string hashName, byte[] secret, byte[] seed, int length)
  76. {
  77. int hashLength = hashName == "MD5" ? 16 : 20;
  78. int iterations = (int)(length / hashLength);
  79. if ((length % hashLength) > 0)
  80. {
  81. iterations++;
  82. }
  83. M.HMAC hmac = new M.HMAC(hashName, secret);
  84. MemoryStream resMacs = new MemoryStream ();
  85. byte[][] hmacs = new byte[iterations + 1][];
  86. hmacs[0] = seed;
  87. for (int i = 1; i <= iterations; i++)
  88. {
  89. MemoryStream hcseed = new MemoryStream ();
  90. hmac.TransformFinalBlock(hmacs[i-1], 0, hmacs[i-1].Length);
  91. hmacs[i] = hmac.Hash;
  92. hcseed.Write(hmacs[i], 0, hmacs [i].Length);
  93. hcseed.Write(seed, 0, seed.Length);
  94. hmac.TransformFinalBlock(hcseed.ToArray(), 0, (int)hcseed.Length);
  95. resMacs.Write(hmac.Hash, 0, hmac.Hash.Length);
  96. }
  97. byte[] res = new byte[length];
  98. Buffer.BlockCopy(resMacs.ToArray(), 0, res, 0, res.Length);
  99. return res;
  100. }
  101. public override byte [] GetSymmetricKey ()
  102. {
  103. return (byte []) key.Clone ();
  104. }
  105. public override KeyedHashAlgorithm GetKeyedHashAlgorithm (
  106. string algorithm)
  107. {
  108. if (algorithm == SecurityAlgorithms.HmacSha1Signature)
  109. return new HMACSHA1 (key);
  110. //if (algorithm == SecurityAlgorithms.HmacSha256Signature)
  111. // return new HMACSHA256 (key);
  112. throw new NotSupportedException ();
  113. }
  114. public override SymmetricAlgorithm GetSymmetricAlgorithm (string algorithm)
  115. {
  116. SymmetricAlgorithm s = null;
  117. switch (algorithm) {
  118. case SecurityAlgorithms.Aes128Encryption:
  119. case SecurityAlgorithms.Aes192Encryption:
  120. case SecurityAlgorithms.Aes256Encryption:
  121. case SecurityAlgorithms.Aes128KeyWrap:
  122. case SecurityAlgorithms.Aes192KeyWrap:
  123. case SecurityAlgorithms.Aes256KeyWrap:
  124. s = new AES ();
  125. break;
  126. case SecurityAlgorithms.TripleDesEncryption:
  127. case SecurityAlgorithms.TripleDesKeyWrap:
  128. if (key.Length == 24)
  129. throw new CryptographicException ("The key size is 24 bytes, which known as vulnerable and thus not allowed.");
  130. s = TripleDES.Create ();
  131. break;
  132. default:
  133. throw new NotSupportedException (String.Format ("This symmetric security key does not support specified algorithm '{0}'", algorithm));
  134. }
  135. s.Mode = CipherMode.CBC;
  136. s.GenerateIV ();
  137. s.Key = key;
  138. return s;
  139. }
  140. public override ICryptoTransform GetDecryptionTransform (string algorithm, byte [] iv)
  141. {
  142. if (iv == null)
  143. throw new ArgumentNullException ("iv");
  144. SymmetricAlgorithm alg = GetSymmetricAlgorithm (algorithm);
  145. alg.IV = iv;
  146. return alg.CreateDecryptor ();
  147. }
  148. public override ICryptoTransform GetEncryptionTransform (string algorithm, byte [] iv)
  149. {
  150. if (iv == null)
  151. throw new ArgumentNullException ("iv");
  152. SymmetricAlgorithm alg = GetSymmetricAlgorithm (algorithm);
  153. alg.IV = iv;
  154. return alg.CreateEncryptor ();
  155. }
  156. [MonoTODO]
  157. public override int GetIVSize (string algorithm)
  158. {
  159. throw new NotImplementedException ();
  160. }
  161. // SecurityKey implementation
  162. public override int KeySize {
  163. get { return key.Length << 3; }
  164. }
  165. public override byte [] DecryptKey (string algorithm, byte [] keyData)
  166. {
  167. if (algorithm == null)
  168. throw new ArgumentNullException ("algorithm");
  169. if (keyData == null)
  170. throw new ArgumentNullException ("keyData");
  171. return EncryptedXml.DecryptKey (keyData, GetSymmetricAlgorithm (algorithm));
  172. }
  173. public override byte [] EncryptKey (string algorithm, byte [] keyData)
  174. {
  175. if (algorithm == null)
  176. throw new ArgumentNullException ("algorithm");
  177. if (keyData == null)
  178. throw new ArgumentNullException ("keyData");
  179. return EncryptedXml.EncryptKey (keyData, GetSymmetricAlgorithm (algorithm));
  180. }
  181. public override bool IsAsymmetricAlgorithm (string algorithm)
  182. {
  183. return GetAlgorithmSupportType (algorithm) == AlgorithmSupportType.Asymmetric;
  184. }
  185. public override bool IsSupportedAlgorithm (string algorithm)
  186. {
  187. switch (algorithm) {
  188. case SecurityAlgorithms.HmacSha1Signature:
  189. case SecurityAlgorithms.Psha1KeyDerivation:
  190. case SecurityAlgorithms.Aes128Encryption:
  191. case SecurityAlgorithms.Aes128KeyWrap:
  192. case SecurityAlgorithms.Aes192Encryption:
  193. case SecurityAlgorithms.Aes192KeyWrap:
  194. case SecurityAlgorithms.Aes256Encryption:
  195. case SecurityAlgorithms.Aes256KeyWrap:
  196. case SecurityAlgorithms.TripleDesEncryption:
  197. case SecurityAlgorithms.TripleDesKeyWrap:
  198. return true;
  199. default:
  200. return false;
  201. }
  202. }
  203. public override bool IsSymmetricAlgorithm (string algorithm)
  204. {
  205. return GetAlgorithmSupportType (algorithm) == AlgorithmSupportType.Symmetric;
  206. }
  207. }
  208. }