CMSEnvelopedDataStreamGenerator.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
  17. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  18. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  19. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  20. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Cms
  21. {
  22. /**
  23. * General class for generating a CMS enveloped-data message stream.
  24. * <p>
  25. * A simple example of usage.
  26. * <pre>
  27. * CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
  28. *
  29. * edGen.AddKeyTransRecipient(cert);
  30. *
  31. * MemoryStream bOut = new MemoryStream();
  32. *
  33. * Stream out = edGen.Open(
  34. * bOut, CMSEnvelopedDataGenerator.AES128_CBC);*
  35. * out.Write(data);
  36. *
  37. * out.Close();
  38. * </pre>
  39. * </p>
  40. */
  41. public class CmsEnvelopedDataStreamGenerator
  42. : CmsEnvelopedGenerator
  43. {
  44. private object _originatorInfo = null;
  45. private object _unprotectedAttributes = null;
  46. private int _bufferSize;
  47. private bool _berEncodeRecipientSet;
  48. public CmsEnvelopedDataStreamGenerator()
  49. {
  50. }
  51. /// <summary>Constructor allowing specific source of randomness</summary>
  52. /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
  53. public CmsEnvelopedDataStreamGenerator(
  54. SecureRandom rand)
  55. : base(rand)
  56. {
  57. }
  58. /// <summary>Set the underlying string size for encapsulated data.</summary>
  59. /// <param name="bufferSize">Length of octet strings to buffer the data.</param>
  60. public void SetBufferSize(
  61. int bufferSize)
  62. {
  63. _bufferSize = bufferSize;
  64. }
  65. /// <summary>Use a BER Set to store the recipient information.</summary>
  66. public void SetBerEncodeRecipients(
  67. bool berEncodeRecipientSet)
  68. {
  69. _berEncodeRecipientSet = berEncodeRecipientSet;
  70. }
  71. private DerInteger Version
  72. {
  73. get
  74. {
  75. int version = (_originatorInfo != null || _unprotectedAttributes != null)
  76. ? 2
  77. : 0;
  78. return new DerInteger(version);
  79. }
  80. }
  81. /// <summary>
  82. /// Generate an enveloped object that contains an CMS Enveloped Data
  83. /// object using the passed in key generator.
  84. /// </summary>
  85. private Stream Open(
  86. Stream outStream,
  87. string encryptionOid,
  88. CipherKeyGenerator keyGen)
  89. {
  90. byte[] encKeyBytes = keyGen.GenerateKey();
  91. KeyParameter encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);
  92. Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);
  93. ICipherParameters cipherParameters;
  94. AlgorithmIdentifier encAlgID = GetAlgorithmIdentifier(
  95. encryptionOid, encKey, asn1Params, out cipherParameters);
  96. Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
  97. foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
  98. {
  99. try
  100. {
  101. recipientInfos.Add(rig.Generate(encKey, rand));
  102. }
  103. catch (InvalidKeyException e)
  104. {
  105. throw new CmsException("key inappropriate for algorithm.", e);
  106. }
  107. catch (GeneralSecurityException e)
  108. {
  109. throw new CmsException("error making encrypted content.", e);
  110. }
  111. }
  112. return Open(outStream, encAlgID, cipherParameters, recipientInfos);
  113. }
  114. private Stream Open(
  115. Stream outStream,
  116. AlgorithmIdentifier encAlgID,
  117. ICipherParameters cipherParameters,
  118. Asn1EncodableVector recipientInfos)
  119. {
  120. try
  121. {
  122. //
  123. // ContentInfo
  124. //
  125. BerSequenceGenerator cGen = new BerSequenceGenerator(outStream);
  126. cGen.AddObject(CmsObjectIdentifiers.EnvelopedData);
  127. //
  128. // Encrypted Data
  129. //
  130. BerSequenceGenerator envGen = new BerSequenceGenerator(
  131. cGen.GetRawOutputStream(), 0, true);
  132. envGen.AddObject(this.Version);
  133. Stream envRaw = envGen.GetRawOutputStream();
  134. Asn1Generator recipGen = _berEncodeRecipientSet
  135. ? (Asn1Generator) new BerSetGenerator(envRaw)
  136. : new DerSetGenerator(envRaw);
  137. foreach (Asn1Encodable ae in recipientInfos)
  138. {
  139. recipGen.AddObject(ae);
  140. }
  141. recipGen.Close();
  142. BerSequenceGenerator eiGen = new BerSequenceGenerator(envRaw);
  143. eiGen.AddObject(CmsObjectIdentifiers.Data);
  144. eiGen.AddObject(encAlgID);
  145. Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
  146. eiGen.GetRawOutputStream(), 0, false, _bufferSize);
  147. IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.Algorithm);
  148. cipher.Init(true, new ParametersWithRandom(cipherParameters, rand));
  149. CipherStream cOut = new CipherStream(octetOutputStream, null, cipher);
  150. return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen);
  151. }
  152. catch (SecurityUtilityException e)
  153. {
  154. throw new CmsException("couldn't create cipher.", e);
  155. }
  156. catch (InvalidKeyException e)
  157. {
  158. throw new CmsException("key invalid in message.", e);
  159. }
  160. catch (IOException e)
  161. {
  162. throw new CmsException("exception decoding algorithm parameters.", e);
  163. }
  164. }
  165. /**
  166. * generate an enveloped object that contains an CMS Enveloped Data object
  167. * @throws IOException
  168. */
  169. public Stream Open(
  170. Stream outStream,
  171. string encryptionOid)
  172. {
  173. CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
  174. keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
  175. return Open(outStream, encryptionOid, keyGen);
  176. }
  177. /**
  178. * generate an enveloped object that contains an CMS Enveloped Data object
  179. * @throws IOException
  180. */
  181. public Stream Open(
  182. Stream outStream,
  183. string encryptionOid,
  184. int keySize)
  185. {
  186. CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
  187. keyGen.Init(new KeyGenerationParameters(rand, keySize));
  188. return Open(outStream, encryptionOid, keyGen);
  189. }
  190. private class CmsEnvelopedDataOutputStream
  191. : BaseOutputStream
  192. {
  193. private readonly CmsEnvelopedGenerator _outer;
  194. private readonly CipherStream _out;
  195. private readonly BerSequenceGenerator _cGen;
  196. private readonly BerSequenceGenerator _envGen;
  197. private readonly BerSequenceGenerator _eiGen;
  198. public CmsEnvelopedDataOutputStream(
  199. CmsEnvelopedGenerator outer,
  200. CipherStream outStream,
  201. BerSequenceGenerator cGen,
  202. BerSequenceGenerator envGen,
  203. BerSequenceGenerator eiGen)
  204. {
  205. _outer = outer;
  206. _out = outStream;
  207. _cGen = cGen;
  208. _envGen = envGen;
  209. _eiGen = eiGen;
  210. }
  211. public override void WriteByte(
  212. byte b)
  213. {
  214. _out.WriteByte(b);
  215. }
  216. public override void Write(
  217. byte[] bytes,
  218. int off,
  219. int len)
  220. {
  221. _out.Write(bytes, off, len);
  222. }
  223. #if PORTABLE || NETFX_CORE
  224. protected override void Dispose(bool disposing)
  225. {
  226. if (disposing)
  227. {
  228. BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(_out);
  229. // TODO Parent context(s) should really be closed explicitly
  230. _eiGen.Close();
  231. if (_outer.unprotectedAttributeGenerator != null)
  232. {
  233. Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable());
  234. Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector());
  235. _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
  236. }
  237. _envGen.Close();
  238. _cGen.Close();
  239. }
  240. base.Dispose(disposing);
  241. }
  242. #else
  243. public override void Close()
  244. {
  245. BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(_out);
  246. // TODO Parent context(s) should really be closed explicitly
  247. _eiGen.Close();
  248. if (_outer.unprotectedAttributeGenerator != null)
  249. {
  250. Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable());
  251. Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector());
  252. _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
  253. }
  254. _envGen.Close();
  255. _cGen.Close();
  256. base.Close();
  257. }
  258. #endif
  259. }
  260. }
  261. }
  262. #pragma warning restore
  263. #endif