CMSSignedData.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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.Utilities.Collections;
  9. using Best.HTTP.SecureProtocol.Org.BouncyCastle.X509;
  10. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Cms
  11. {
  12. /**
  13. * general class for handling a pkcs7-signature message.
  14. *
  15. * A simple example of usage - note, in the example below the validity of
  16. * the certificate isn't verified, just the fact that one of the certs
  17. * matches the given signer...
  18. *
  19. * <pre>
  20. * IX509Store certs = s.GetCertificates();
  21. * SignerInformationStore signers = s.GetSignerInfos();
  22. *
  23. * foreach (SignerInformation signer in signers.GetSigners())
  24. * {
  25. * ArrayList certList = new ArrayList(certs.GetMatches(signer.SignerID));
  26. * X509Certificate cert = (X509Certificate) certList[0];
  27. *
  28. * if (signer.Verify(cert.GetPublicKey()))
  29. * {
  30. * verified++;
  31. * }
  32. * }
  33. * </pre>
  34. */
  35. public class CmsSignedData
  36. {
  37. private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
  38. private readonly CmsProcessable signedContent;
  39. private SignedData signedData;
  40. private ContentInfo contentInfo;
  41. private SignerInformationStore signerInfoStore;
  42. private IDictionary<string, byte[]> m_hashes;
  43. private CmsSignedData(CmsSignedData c)
  44. {
  45. this.signedData = c.signedData;
  46. this.contentInfo = c.contentInfo;
  47. this.signedContent = c.signedContent;
  48. this.signerInfoStore = c.signerInfoStore;
  49. }
  50. public CmsSignedData(byte[] sigBlock)
  51. : this(CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false)))
  52. {
  53. }
  54. public CmsSignedData(CmsProcessable signedContent, byte[] sigBlock)
  55. : this(signedContent, CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false)))
  56. {
  57. }
  58. /**
  59. * Content with detached signature, digests precomputed
  60. *
  61. * @param hashes a map of precomputed digests for content indexed by name of hash.
  62. * @param sigBlock the signature object.
  63. */
  64. public CmsSignedData(IDictionary<string, byte[]> hashes, byte[] sigBlock)
  65. : this(hashes, CmsUtilities.ReadContentInfo(sigBlock))
  66. {
  67. }
  68. /**
  69. * base constructor - content with detached signature.
  70. *
  71. * @param signedContent the content that was signed.
  72. * @param sigData the signature object.
  73. */
  74. public CmsSignedData(CmsProcessable signedContent, Stream sigData)
  75. : this(signedContent, CmsUtilities.ReadContentInfo(sigData))
  76. {
  77. }
  78. /**
  79. * base constructor - with encapsulated content
  80. */
  81. public CmsSignedData(Stream sigData)
  82. : this(CmsUtilities.ReadContentInfo(sigData))
  83. {
  84. }
  85. public CmsSignedData(CmsProcessable signedContent, ContentInfo sigData)
  86. {
  87. this.signedContent = signedContent;
  88. this.contentInfo = sigData;
  89. this.signedData = SignedData.GetInstance(contentInfo.Content);
  90. }
  91. public CmsSignedData(IDictionary<string, byte[]> hashes, ContentInfo sigData)
  92. {
  93. this.m_hashes = hashes;
  94. this.contentInfo = sigData;
  95. this.signedData = SignedData.GetInstance(contentInfo.Content);
  96. }
  97. public CmsSignedData(ContentInfo sigData)
  98. {
  99. this.contentInfo = sigData;
  100. this.signedData = SignedData.GetInstance(contentInfo.Content);
  101. //
  102. // this can happen if the signed message is sent simply to send a
  103. // certificate chain.
  104. //
  105. if (signedData.EncapContentInfo.Content != null)
  106. {
  107. this.signedContent = new CmsProcessableByteArray(
  108. ((Asn1OctetString)(signedData.EncapContentInfo.Content)).GetOctets());
  109. }
  110. // else
  111. // {
  112. // this.signedContent = null;
  113. // }
  114. }
  115. /// <summary>Return the version number for this object.</summary>
  116. public int Version
  117. {
  118. get { return signedData.Version.IntValueExact; }
  119. }
  120. /**
  121. * return the collection of signers that are associated with the
  122. * signatures for the message.
  123. */
  124. public SignerInformationStore GetSignerInfos()
  125. {
  126. if (signerInfoStore == null)
  127. {
  128. var signerInfos = new List<SignerInformation>();
  129. Asn1Set s = signedData.SignerInfos;
  130. foreach (object obj in s)
  131. {
  132. SignerInfo info = SignerInfo.GetInstance(obj);
  133. DerObjectIdentifier contentType = signedData.EncapContentInfo.ContentType;
  134. if (m_hashes == null)
  135. {
  136. signerInfos.Add(new SignerInformation(info, contentType, signedContent, null));
  137. }
  138. else if (m_hashes.TryGetValue(info.DigestAlgorithm.Algorithm.Id, out var hash))
  139. {
  140. signerInfos.Add(new SignerInformation(info, contentType, null, new BaseDigestCalculator(hash)));
  141. }
  142. else
  143. {
  144. throw new InvalidOperationException();
  145. }
  146. }
  147. signerInfoStore = new SignerInformationStore(signerInfos);
  148. }
  149. return signerInfoStore;
  150. }
  151. /**
  152. * return a X509Store containing the attribute certificates, if any, contained
  153. * in this message.
  154. *
  155. * @param type type of store to create
  156. * @return a store of attribute certificates
  157. * @exception NoSuchStoreException if the store type isn't available.
  158. * @exception CmsException if a general exception prevents creation of the X509Store
  159. */
  160. public IStore<X509V2AttributeCertificate> GetAttributeCertificates()
  161. {
  162. return Helper.GetAttributeCertificates(signedData.Certificates);
  163. }
  164. /**
  165. * return a X509Store containing the public key certificates, if any, contained in this message.
  166. *
  167. * @return a store of public key certificates
  168. * @exception NoSuchStoreException if the store type isn't available.
  169. * @exception CmsException if a general exception prevents creation of the X509Store
  170. */
  171. public IStore<X509Certificate> GetCertificates()
  172. {
  173. return Helper.GetCertificates(signedData.Certificates);
  174. }
  175. /**
  176. * return a X509Store containing CRLs, if any, contained in this message.
  177. *
  178. * @return a store of CRLs
  179. * @exception NoSuchStoreException if the store type isn't available.
  180. * @exception CmsException if a general exception prevents creation of the X509Store
  181. */
  182. public IStore<X509Crl> GetCrls()
  183. {
  184. return Helper.GetCrls(signedData.CRLs);
  185. }
  186. public IStore<Asn1Encodable> GetOtherRevInfos(DerObjectIdentifier otherRevInfoFormat)
  187. {
  188. return Helper.GetOtherRevInfos(signedData.CRLs, otherRevInfoFormat);
  189. }
  190. /// <summary>
  191. /// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
  192. /// content info structure carried in the signed data.
  193. /// </summary>
  194. public DerObjectIdentifier SignedContentType
  195. {
  196. get { return signedData.EncapContentInfo.ContentType; }
  197. }
  198. public CmsProcessable SignedContent
  199. {
  200. get { return signedContent; }
  201. }
  202. /**
  203. * return the ContentInfo
  204. */
  205. public ContentInfo ContentInfo
  206. {
  207. get { return contentInfo; }
  208. }
  209. /**
  210. * return the ASN.1 encoded representation of this object.
  211. */
  212. public byte[] GetEncoded()
  213. {
  214. return contentInfo.GetEncoded();
  215. }
  216. /**
  217. * return the ASN.1 encoded representation of this object using the specified encoding.
  218. *
  219. * @param encoding the ASN.1 encoding format to use ("BER" or "DER").
  220. */
  221. public byte[] GetEncoded(string encoding)
  222. {
  223. return contentInfo.GetEncoded(encoding);
  224. }
  225. /**
  226. * Replace the signerinformation store associated with this
  227. * CmsSignedData object with the new one passed in. You would
  228. * probably only want to do this if you wanted to change the unsigned
  229. * attributes associated with a signer, or perhaps delete one.
  230. *
  231. * @param signedData the signed data object to be used as a base.
  232. * @param signerInformationStore the new signer information store to use.
  233. * @return a new signed data object.
  234. */
  235. public static CmsSignedData ReplaceSigners(
  236. CmsSignedData signedData,
  237. SignerInformationStore signerInformationStore)
  238. {
  239. //
  240. // copy
  241. //
  242. CmsSignedData cms = new CmsSignedData(signedData);
  243. //
  244. // replace the store
  245. //
  246. cms.signerInfoStore = signerInformationStore;
  247. //
  248. // replace the signers in the SignedData object
  249. //
  250. Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
  251. Asn1EncodableVector vec = new Asn1EncodableVector();
  252. foreach (SignerInformation signer in signerInformationStore.GetSigners())
  253. {
  254. digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
  255. vec.Add(signer.ToSignerInfo());
  256. }
  257. Asn1Set digests = new DerSet(digestAlgs);
  258. Asn1Set signers = new DerSet(vec);
  259. Asn1Sequence sD = (Asn1Sequence)signedData.signedData.ToAsn1Object();
  260. //
  261. // signers are the last item in the sequence.
  262. //
  263. vec = new Asn1EncodableVector(
  264. sD[0], // version
  265. digests);
  266. for (int i = 2; i != sD.Count - 1; i++)
  267. {
  268. vec.Add(sD[i]);
  269. }
  270. vec.Add(signers);
  271. cms.signedData = SignedData.GetInstance(new BerSequence(vec));
  272. //
  273. // replace the contentInfo with the new one
  274. //
  275. cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
  276. return cms;
  277. }
  278. /**
  279. * Replace the certificate and CRL information associated with this
  280. * CmsSignedData object with the new one passed in.
  281. *
  282. * @param signedData the signed data object to be used as a base.
  283. * @param x509Certs the new certificates to be used.
  284. * @param x509Crls the new CRLs to be used.
  285. * @return a new signed data object.
  286. * @exception CmsException if there is an error processing the stores
  287. */
  288. public static CmsSignedData ReplaceCertificatesAndCrls(CmsSignedData signedData,
  289. IStore<X509Certificate> x509Certs, IStore<X509Crl> x509Crls)
  290. {
  291. return ReplaceCertificatesAndRevocations(signedData, x509Certs, x509Crls, null, null);
  292. }
  293. public static CmsSignedData ReplaceCertificatesAndCrls(CmsSignedData signedData,
  294. IStore<X509Certificate> x509Certs, IStore<X509Crl> x509Crls,
  295. IStore<X509V2AttributeCertificate> x509AttrCerts)
  296. {
  297. return ReplaceCertificatesAndRevocations(signedData, x509Certs, x509Crls, x509AttrCerts, null);
  298. }
  299. public static CmsSignedData ReplaceCertificatesAndRevocations(CmsSignedData signedData,
  300. IStore<X509Certificate> x509Certs, IStore<X509Crl> x509Crls,
  301. IStore<X509V2AttributeCertificate> x509AttrCerts, IStore<OtherRevocationInfoFormat> otherRevocationInfos)
  302. {
  303. //
  304. // copy
  305. //
  306. CmsSignedData cms = new CmsSignedData(signedData);
  307. //
  308. // replace the certs and crls in the SignedData object
  309. //
  310. Asn1Set certSet = null;
  311. Asn1Set revocationSet = null;
  312. if (x509Certs != null || x509AttrCerts != null)
  313. {
  314. var certificates = new List<Asn1Encodable>();
  315. if (x509Certs != null)
  316. {
  317. certificates.AddRange(CmsUtilities.GetCertificatesFromStore(x509Certs));
  318. }
  319. if (x509AttrCerts != null)
  320. {
  321. certificates.AddRange(CmsUtilities.GetAttributeCertificatesFromStore(x509AttrCerts));
  322. }
  323. Asn1Set berSet = CmsUtilities.CreateBerSetFromList(certificates);
  324. if (berSet.Count > 0)
  325. {
  326. certSet = berSet;
  327. }
  328. }
  329. if (x509Crls != null || otherRevocationInfos != null)
  330. {
  331. var revocations = new List<Asn1Encodable>();
  332. if (x509Crls != null)
  333. {
  334. revocations.AddRange(CmsUtilities.GetCrlsFromStore(x509Crls));
  335. }
  336. if (otherRevocationInfos != null)
  337. {
  338. revocations.AddRange(CmsUtilities.GetOtherRevocationInfosFromStore(otherRevocationInfos));
  339. }
  340. Asn1Set berSet = CmsUtilities.CreateBerSetFromList(revocations);
  341. if (berSet.Count > 0)
  342. {
  343. revocationSet = berSet;
  344. }
  345. }
  346. //
  347. // replace the CMS structure.
  348. //
  349. SignedData old = signedData.signedData;
  350. cms.signedData = new SignedData(
  351. old.DigestAlgorithms,
  352. old.EncapContentInfo,
  353. certSet,
  354. revocationSet,
  355. old.SignerInfos);
  356. //
  357. // replace the contentInfo with the new one
  358. //
  359. cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
  360. return cms;
  361. }
  362. }
  363. }
  364. #pragma warning restore
  365. #endif