SignedData.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cms
  5. {
  6. /**
  7. * a signed data object.
  8. */
  9. public class SignedData
  10. : Asn1Encodable
  11. {
  12. private static readonly DerInteger Version1 = new DerInteger(1);
  13. private static readonly DerInteger Version3 = new DerInteger(3);
  14. private static readonly DerInteger Version4 = new DerInteger(4);
  15. private static readonly DerInteger Version5 = new DerInteger(5);
  16. private readonly DerInteger version;
  17. private readonly Asn1Set digestAlgorithms;
  18. private readonly ContentInfo contentInfo;
  19. private readonly Asn1Set certificates;
  20. private readonly Asn1Set crls;
  21. private readonly Asn1Set signerInfos;
  22. private readonly bool certsBer;
  23. private readonly bool crlsBer;
  24. public static SignedData GetInstance(object obj)
  25. {
  26. if (obj is SignedData)
  27. return (SignedData)obj;
  28. if (obj == null)
  29. return null;
  30. return new SignedData(Asn1Sequence.GetInstance(obj));
  31. }
  32. public SignedData(
  33. Asn1Set digestAlgorithms,
  34. ContentInfo contentInfo,
  35. Asn1Set certificates,
  36. Asn1Set crls,
  37. Asn1Set signerInfos)
  38. {
  39. this.version = CalculateVersion(contentInfo.ContentType, certificates, crls, signerInfos);
  40. this.digestAlgorithms = digestAlgorithms;
  41. this.contentInfo = contentInfo;
  42. this.certificates = certificates;
  43. this.crls = crls;
  44. this.signerInfos = signerInfos;
  45. this.crlsBer = crls is BerSet;
  46. this.certsBer = certificates is BerSet;
  47. }
  48. // RFC3852, section 5.1:
  49. // IF ((certificates is present) AND
  50. // (any certificates with a type of other are present)) OR
  51. // ((crls is present) AND
  52. // (any crls with a type of other are present))
  53. // THEN version MUST be 5
  54. // ELSE
  55. // IF (certificates is present) AND
  56. // (any version 2 attribute certificates are present)
  57. // THEN version MUST be 4
  58. // ELSE
  59. // IF ((certificates is present) AND
  60. // (any version 1 attribute certificates are present)) OR
  61. // (any SignerInfo structures are version 3) OR
  62. // (encapContentInfo eContentType is other than id-data)
  63. // THEN version MUST be 3
  64. // ELSE version MUST be 1
  65. //
  66. private DerInteger CalculateVersion(
  67. DerObjectIdentifier contentOid,
  68. Asn1Set certs,
  69. Asn1Set crls,
  70. Asn1Set signerInfs)
  71. {
  72. bool otherCert = false;
  73. bool otherCrl = false;
  74. bool attrCertV1Found = false;
  75. bool attrCertV2Found = false;
  76. if (certs != null)
  77. {
  78. foreach (object obj in certs)
  79. {
  80. if (obj is Asn1TaggedObject)
  81. {
  82. Asn1TaggedObject tagged = (Asn1TaggedObject)obj;
  83. if (tagged.TagNo == 1)
  84. {
  85. attrCertV1Found = true;
  86. }
  87. else if (tagged.TagNo == 2)
  88. {
  89. attrCertV2Found = true;
  90. }
  91. else if (tagged.TagNo == 3)
  92. {
  93. otherCert = true;
  94. break;
  95. }
  96. }
  97. }
  98. }
  99. if (otherCert)
  100. {
  101. return Version5;
  102. }
  103. if (crls != null)
  104. {
  105. foreach (object obj in crls)
  106. {
  107. if (obj is Asn1TaggedObject)
  108. {
  109. otherCrl = true;
  110. break;
  111. }
  112. }
  113. }
  114. if (otherCrl)
  115. {
  116. return Version5;
  117. }
  118. if (attrCertV2Found)
  119. {
  120. return Version4;
  121. }
  122. if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs))
  123. {
  124. return Version3;
  125. }
  126. return Version1;
  127. }
  128. private bool CheckForVersion3(Asn1Set signerInfs)
  129. {
  130. foreach (object obj in signerInfs)
  131. {
  132. SignerInfo s = SignerInfo.GetInstance(obj);
  133. if (s.Version.HasValue(3))
  134. {
  135. return true;
  136. }
  137. }
  138. return false;
  139. }
  140. private SignedData(Asn1Sequence seq)
  141. {
  142. var e = seq.GetEnumerator();
  143. e.MoveNext();
  144. version = (DerInteger)e.Current;
  145. e.MoveNext();
  146. digestAlgorithms = (Asn1Set)e.Current.ToAsn1Object();
  147. e.MoveNext();
  148. contentInfo = ContentInfo.GetInstance(e.Current.ToAsn1Object());
  149. while (e.MoveNext())
  150. {
  151. Asn1Object o = e.Current.ToAsn1Object();
  152. //
  153. // an interesting feature of SignedData is that there appear
  154. // to be varying implementations...
  155. // for the moment we ignore anything which doesn't fit.
  156. //
  157. if (o is Asn1TaggedObject tagged)
  158. {
  159. switch (tagged.TagNo)
  160. {
  161. case 0:
  162. certsBer = tagged is BerTaggedObject;
  163. certificates = Asn1Set.GetInstance(tagged, false);
  164. break;
  165. case 1:
  166. crlsBer = tagged is BerTaggedObject;
  167. crls = Asn1Set.GetInstance(tagged, false);
  168. break;
  169. default:
  170. throw new ArgumentException("unknown tag value " + tagged.TagNo);
  171. }
  172. }
  173. else
  174. {
  175. signerInfos = (Asn1Set) o;
  176. }
  177. }
  178. }
  179. public DerInteger Version
  180. {
  181. get { return version; }
  182. }
  183. public Asn1Set DigestAlgorithms
  184. {
  185. get { return digestAlgorithms; }
  186. }
  187. public ContentInfo EncapContentInfo
  188. {
  189. get { return contentInfo; }
  190. }
  191. public Asn1Set Certificates
  192. {
  193. get { return certificates; }
  194. }
  195. public Asn1Set CRLs
  196. {
  197. get { return crls; }
  198. }
  199. public Asn1Set SignerInfos
  200. {
  201. get { return signerInfos; }
  202. }
  203. /**
  204. * Produce an object suitable for an Asn1OutputStream.
  205. * <pre>
  206. * SignedData ::= Sequence {
  207. * version CMSVersion,
  208. * digestAlgorithms DigestAlgorithmIdentifiers,
  209. * encapContentInfo EncapsulatedContentInfo,
  210. * certificates [0] IMPLICIT CertificateSet OPTIONAL,
  211. * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  212. * signerInfos SignerInfos
  213. * }
  214. * </pre>
  215. */
  216. public override Asn1Object ToAsn1Object()
  217. {
  218. Asn1EncodableVector v = new Asn1EncodableVector(
  219. version, digestAlgorithms, contentInfo);
  220. if (certificates != null)
  221. {
  222. if (certsBer)
  223. {
  224. v.Add(new BerTaggedObject(false, 0, certificates));
  225. }
  226. else
  227. {
  228. v.Add(new DerTaggedObject(false, 0, certificates));
  229. }
  230. }
  231. if (crls != null)
  232. {
  233. if (crlsBer)
  234. {
  235. v.Add(new BerTaggedObject(false, 1, crls));
  236. }
  237. else
  238. {
  239. v.Add(new DerTaggedObject(false, 1, crls));
  240. }
  241. }
  242. v.Add(signerInfos);
  243. return new BerSequence(v);
  244. }
  245. }
  246. }
  247. #pragma warning restore
  248. #endif