CMSEnvelopedHelper.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  9. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  10. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO;
  11. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  12. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  13. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  14. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Cms
  15. {
  16. class CmsEnvelopedHelper
  17. {
  18. internal static readonly CmsEnvelopedHelper Instance = new CmsEnvelopedHelper();
  19. private static readonly IDictionary<string, int> KeySizes = new Dictionary<string, int>();
  20. private static readonly IDictionary<string, string> BaseCipherNames = new Dictionary<string, string>();
  21. static CmsEnvelopedHelper()
  22. {
  23. KeySizes.Add(CmsEnvelopedGenerator.DesEde3Cbc, 192);
  24. KeySizes.Add(CmsEnvelopedGenerator.Aes128Cbc, 128);
  25. KeySizes.Add(CmsEnvelopedGenerator.Aes192Cbc, 192);
  26. KeySizes.Add(CmsEnvelopedGenerator.Aes256Cbc, 256);
  27. BaseCipherNames.Add(CmsEnvelopedGenerator.DesEde3Cbc, "DESEDE");
  28. BaseCipherNames.Add(CmsEnvelopedGenerator.Aes128Cbc, "AES");
  29. BaseCipherNames.Add(CmsEnvelopedGenerator.Aes192Cbc, "AES");
  30. BaseCipherNames.Add(CmsEnvelopedGenerator.Aes256Cbc, "AES");
  31. }
  32. private string GetAsymmetricEncryptionAlgName(
  33. string encryptionAlgOid)
  34. {
  35. if (Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption.Id.Equals(encryptionAlgOid))
  36. {
  37. return "RSA/ECB/PKCS1Padding";
  38. }
  39. return encryptionAlgOid;
  40. }
  41. internal IBufferedCipher CreateAsymmetricCipher(
  42. string encryptionOid)
  43. {
  44. string asymName = GetAsymmetricEncryptionAlgName(encryptionOid);
  45. if (!asymName.Equals(encryptionOid))
  46. {
  47. try
  48. {
  49. return CipherUtilities.GetCipher(asymName);
  50. }
  51. catch (SecurityUtilityException)
  52. {
  53. // Ignore
  54. }
  55. }
  56. return CipherUtilities.GetCipher(encryptionOid);
  57. }
  58. internal IWrapper CreateWrapper(
  59. string encryptionOid)
  60. {
  61. try
  62. {
  63. return WrapperUtilities.GetWrapper(encryptionOid);
  64. }
  65. catch (SecurityUtilityException)
  66. {
  67. return WrapperUtilities.GetWrapper(GetAsymmetricEncryptionAlgName(encryptionOid));
  68. }
  69. }
  70. internal string GetRfc3211WrapperName(string oid)
  71. {
  72. if (oid == null)
  73. throw new ArgumentNullException(nameof(oid));
  74. if (!BaseCipherNames.TryGetValue(oid, out var alg))
  75. throw new ArgumentException("no name for " + oid, nameof(oid));
  76. return alg + "RFC3211Wrap";
  77. }
  78. internal int GetKeySize(string oid)
  79. {
  80. if (oid == null)
  81. throw new ArgumentNullException(nameof(oid));
  82. if (!KeySizes.TryGetValue(oid, out var keySize))
  83. throw new ArgumentException("no keysize for " + oid, "oid");
  84. return keySize;
  85. }
  86. internal static RecipientInformationStore BuildRecipientInformationStore(
  87. Asn1Set recipientInfos, CmsSecureReadable secureReadable)
  88. {
  89. var infos = new List<RecipientInformation>();
  90. for (int i = 0; i != recipientInfos.Count; i++)
  91. {
  92. RecipientInfo info = RecipientInfo.GetInstance(recipientInfos[i]);
  93. ReadRecipientInfo(infos, info, secureReadable);
  94. }
  95. return new RecipientInformationStore(infos);
  96. }
  97. private static void ReadRecipientInfo(IList<RecipientInformation> infos, RecipientInfo info,
  98. CmsSecureReadable secureReadable)
  99. {
  100. Asn1Encodable recipInfo = info.Info;
  101. if (recipInfo is KeyTransRecipientInfo keyTransRecipientInfo)
  102. {
  103. infos.Add(new KeyTransRecipientInformation(keyTransRecipientInfo, secureReadable));
  104. }
  105. else if (recipInfo is KekRecipientInfo kekRecipientInfo)
  106. {
  107. infos.Add(new KekRecipientInformation(kekRecipientInfo, secureReadable));
  108. }
  109. else if (recipInfo is KeyAgreeRecipientInfo keyAgreeRecipientInfo)
  110. {
  111. KeyAgreeRecipientInformation.ReadRecipientInfo(infos, keyAgreeRecipientInfo, secureReadable);
  112. }
  113. else if (recipInfo is PasswordRecipientInfo passwordRecipientInfo)
  114. {
  115. infos.Add(new PasswordRecipientInformation(passwordRecipientInfo, secureReadable));
  116. }
  117. }
  118. internal class CmsAuthenticatedSecureReadable : CmsSecureReadable
  119. {
  120. private AlgorithmIdentifier algorithm;
  121. private IMac mac;
  122. private CmsReadable readable;
  123. internal CmsAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
  124. {
  125. this.algorithm = algorithm;
  126. this.readable = readable;
  127. }
  128. public AlgorithmIdentifier Algorithm
  129. {
  130. get { return this.algorithm; }
  131. }
  132. public object CryptoObject
  133. {
  134. get { return this.mac; }
  135. }
  136. public CmsReadable GetReadable(KeyParameter sKey)
  137. {
  138. string macAlg = this.algorithm.Algorithm.Id;
  139. // Asn1Object sParams = this.algorithm.Parameters.ToAsn1Object();
  140. try
  141. {
  142. this.mac = MacUtilities.GetMac(macAlg);
  143. // FIXME Support for MAC algorithm parameters similar to cipher parameters
  144. // ASN1Object sParams = (ASN1Object)macAlg.getParameters();
  145. //
  146. // if (sParams != null && !(sParams instanceof ASN1Null))
  147. // {
  148. // AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE.createAlgorithmParameters(macAlg.getObjectId().getId(), provider);
  149. //
  150. // params.init(sParams.getEncoded(), "ASN.1");
  151. //
  152. // mac.init(sKey, params.getParameterSpec(IvParameterSpec.class));
  153. // }
  154. // else
  155. {
  156. mac.Init(sKey);
  157. }
  158. // Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
  159. //
  160. // ICipherParameters cipherParameters = sKey;
  161. //
  162. // if (asn1Params != null && !(asn1Params is Asn1Null))
  163. // {
  164. // cipherParameters = ParameterUtilities.GetCipherParameters(
  165. // macAlg.Algorithm, cipherParameters, asn1Params);
  166. // }
  167. // else
  168. // {
  169. // string alg = macAlg.Algorithm.Id;
  170. // if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
  171. // || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
  172. // || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
  173. // {
  174. // cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
  175. // }
  176. // }
  177. //
  178. // mac.Init(cipherParameters);
  179. }
  180. catch (SecurityUtilityException e)
  181. {
  182. throw new CmsException("couldn't create cipher.", e);
  183. }
  184. catch (InvalidKeyException e)
  185. {
  186. throw new CmsException("key invalid in message.", e);
  187. }
  188. catch (IOException e)
  189. {
  190. throw new CmsException("error decoding algorithm parameters.", e);
  191. }
  192. try
  193. {
  194. return new CmsProcessableInputStream(
  195. new TeeInputStream(
  196. readable.GetInputStream(),
  197. new MacSink(this.mac)));
  198. }
  199. catch (IOException e)
  200. {
  201. throw new CmsException("error reading content.", e);
  202. }
  203. }
  204. }
  205. internal class CmsEnvelopedSecureReadable : CmsSecureReadable
  206. {
  207. private AlgorithmIdentifier algorithm;
  208. private IBufferedCipher cipher;
  209. private CmsReadable readable;
  210. internal CmsEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
  211. {
  212. this.algorithm = algorithm;
  213. this.readable = readable;
  214. }
  215. public AlgorithmIdentifier Algorithm
  216. {
  217. get { return this.algorithm; }
  218. }
  219. public object CryptoObject
  220. {
  221. get { return this.cipher; }
  222. }
  223. public CmsReadable GetReadable(KeyParameter sKey)
  224. {
  225. try
  226. {
  227. this.cipher = CipherUtilities.GetCipher(this.algorithm.Algorithm);
  228. Asn1Encodable asn1Enc = this.algorithm.Parameters;
  229. Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
  230. ICipherParameters cipherParameters = sKey;
  231. if (asn1Params != null && !(asn1Params is Asn1Null))
  232. {
  233. cipherParameters = ParameterUtilities.GetCipherParameters(
  234. this.algorithm.Algorithm, cipherParameters, asn1Params);
  235. }
  236. else
  237. {
  238. string alg = this.algorithm.Algorithm.Id;
  239. if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
  240. || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
  241. || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
  242. {
  243. cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
  244. }
  245. }
  246. cipher.Init(false, cipherParameters);
  247. }
  248. catch (SecurityUtilityException e)
  249. {
  250. throw new CmsException("couldn't create cipher.", e);
  251. }
  252. catch (InvalidKeyException e)
  253. {
  254. throw new CmsException("key invalid in message.", e);
  255. }
  256. catch (IOException e)
  257. {
  258. throw new CmsException("error decoding algorithm parameters.", e);
  259. }
  260. try
  261. {
  262. return new CmsProcessableInputStream(
  263. new CipherStream(readable.GetInputStream(), cipher, null));
  264. }
  265. catch (IOException e)
  266. {
  267. throw new CmsException("error reading content.", e);
  268. }
  269. }
  270. }
  271. }
  272. }
  273. #pragma warning restore
  274. #endif