TimeStampTokenGenerator.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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 System.Text;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cmp;
  9. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Ess;
  10. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
  11. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
  12. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Tsp;
  13. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  14. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Cms;
  15. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  16. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Operators;
  17. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  18. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  19. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  20. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Date;
  21. using Best.HTTP.SecureProtocol.Org.BouncyCastle.X509;
  22. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tsp
  23. {
  24. public enum Resolution
  25. {
  26. R_SECONDS, R_TENTHS_OF_SECONDS, R_HUNDREDTHS_OF_SECONDS, R_MILLISECONDS
  27. }
  28. public class TimeStampTokenGenerator
  29. {
  30. private int accuracySeconds = -1;
  31. private int accuracyMillis = -1;
  32. private int accuracyMicros = -1;
  33. private bool ordering = false;
  34. private GeneralName tsa = null;
  35. private DerObjectIdentifier tsaPolicyOID;
  36. private IStore<X509Certificate> x509Certs;
  37. private IStore<X509Crl> x509Crls;
  38. private IStore<X509V2AttributeCertificate> x509AttrCerts;
  39. // TODO Port changes from bc-java
  40. //private Dictionary<> otherRevoc = new Dictionary<>();
  41. private SignerInfoGenerator signerInfoGenerator;
  42. IDigestFactory digestCalculator;
  43. private Resolution resolution = Resolution.R_SECONDS;
  44. public Resolution Resolution
  45. {
  46. get { return resolution; }
  47. set { resolution = value; }
  48. }
  49. /**
  50. * basic creation - only the default attributes will be included here.
  51. */
  52. public TimeStampTokenGenerator(
  53. AsymmetricKeyParameter key,
  54. X509Certificate cert,
  55. string digestOID,
  56. string tsaPolicyOID)
  57. : this(key, cert, digestOID, tsaPolicyOID, null, null)
  58. {
  59. }
  60. public TimeStampTokenGenerator(
  61. SignerInfoGenerator signerInfoGen,
  62. IDigestFactory digestCalculator,
  63. DerObjectIdentifier tsaPolicy,
  64. bool isIssuerSerialIncluded)
  65. {
  66. this.signerInfoGenerator = signerInfoGen;
  67. this.digestCalculator = digestCalculator;
  68. this.tsaPolicyOID = tsaPolicy;
  69. if (signerInfoGenerator.certificate == null)
  70. throw new ArgumentException("SignerInfoGenerator must have an associated certificate");
  71. X509Certificate assocCert = signerInfoGenerator.certificate;
  72. TspUtil.ValidateCertificate(assocCert);
  73. try
  74. {
  75. byte[] certEnc = assocCert.GetEncoded();
  76. IStreamCalculator<IBlockResult> calculator = digestCalculator.CreateCalculator();
  77. using (var stream = calculator.Stream)
  78. {
  79. stream.Write(certEnc, 0, certEnc.Length);
  80. }
  81. if (((AlgorithmIdentifier)digestCalculator.AlgorithmDetails).Algorithm.Equals(OiwObjectIdentifiers.IdSha1))
  82. {
  83. EssCertID essCertID = new EssCertID(
  84. calculator.GetResult().Collect(),
  85. isIssuerSerialIncluded ?
  86. new IssuerSerial(
  87. new GeneralNames(
  88. new GeneralName(assocCert.IssuerDN)),
  89. new DerInteger(assocCert.SerialNumber)) : null);
  90. this.signerInfoGenerator = signerInfoGen.NewBuilder()
  91. .WithSignedAttributeGenerator(new TableGen(signerInfoGen, essCertID))
  92. .Build(signerInfoGen.contentSigner, signerInfoGen.certificate);
  93. }
  94. else
  95. {
  96. AlgorithmIdentifier digestAlgID = new AlgorithmIdentifier(
  97. ((AlgorithmIdentifier)digestCalculator.AlgorithmDetails).Algorithm);
  98. EssCertIDv2 essCertID = new EssCertIDv2(
  99. calculator.GetResult().Collect(),
  100. isIssuerSerialIncluded ?
  101. new IssuerSerial(
  102. new GeneralNames(
  103. new GeneralName(assocCert.IssuerDN)),
  104. new DerInteger(assocCert.SerialNumber)) : null);
  105. this.signerInfoGenerator = signerInfoGen.NewBuilder()
  106. .WithSignedAttributeGenerator(new TableGen2(signerInfoGen, essCertID))
  107. .Build(signerInfoGen.contentSigner, signerInfoGen.certificate);
  108. }
  109. }
  110. catch (Exception ex)
  111. {
  112. throw new TspException("Exception processing certificate", ex);
  113. }
  114. }
  115. /**
  116. * create with a signer with extra signed/unsigned attributes.
  117. */
  118. public TimeStampTokenGenerator(
  119. AsymmetricKeyParameter key,
  120. X509Certificate cert,
  121. string digestOID,
  122. string tsaPolicyOID,
  123. Asn1.Cms.AttributeTable signedAttr,
  124. Asn1.Cms.AttributeTable unsignedAttr) : this(
  125. makeInfoGenerator(key, cert, digestOID, signedAttr, unsignedAttr),
  126. Asn1DigestFactory.Get(OiwObjectIdentifiers.IdSha1),
  127. tsaPolicyOID != null ? new DerObjectIdentifier(tsaPolicyOID):null, false)
  128. {
  129. }
  130. internal static SignerInfoGenerator makeInfoGenerator(
  131. AsymmetricKeyParameter key,
  132. X509Certificate cert,
  133. string digestOID,
  134. Asn1.Cms.AttributeTable signedAttr,
  135. Asn1.Cms.AttributeTable unsignedAttr)
  136. {
  137. TspUtil.ValidateCertificate(cert);
  138. //
  139. // Add the ESSCertID attribute
  140. //
  141. IDictionary<DerObjectIdentifier, object> signedAttrs;
  142. if (signedAttr != null)
  143. {
  144. signedAttrs = signedAttr.ToDictionary();
  145. }
  146. else
  147. {
  148. signedAttrs = new Dictionary<DerObjectIdentifier, object>();
  149. }
  150. //try
  151. //{
  152. // byte[] hash = DigestUtilities.CalculateDigest("SHA-1", cert.GetEncoded());
  153. // EssCertID essCertid = new EssCertID(hash);
  154. // Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(
  155. // PkcsObjectIdentifiers.IdAASigningCertificate,
  156. // new DerSet(new SigningCertificate(essCertid)));
  157. // signedAttrs[attr.AttrType] = attr;
  158. //}
  159. //catch (CertificateEncodingException e)
  160. //{
  161. // throw new TspException("Exception processing certificate.", e);
  162. //}
  163. //catch (SecurityUtilityException e)
  164. //{
  165. // throw new TspException("Can't find a SHA-1 implementation.", e);
  166. //}
  167. string digestName = CmsSignedHelper.Instance.GetDigestAlgName(digestOID);
  168. string signatureName = digestName + "with" + CmsSignedHelper.Instance.GetEncryptionAlgName(CmsSignedHelper.Instance.GetEncOid(key, digestOID));
  169. Asn1SignatureFactory sigfact = new Asn1SignatureFactory(signatureName, key);
  170. return new SignerInfoGeneratorBuilder()
  171. .WithSignedAttributeGenerator(
  172. new DefaultSignedAttributeTableGenerator(
  173. new Asn1.Cms.AttributeTable(signedAttrs)))
  174. .WithUnsignedAttributeGenerator(
  175. new SimpleAttributeTableGenerator(unsignedAttr))
  176. .Build(sigfact, cert);
  177. }
  178. public void SetAttributeCertificates(IStore<X509V2AttributeCertificate> attributeCertificates)
  179. {
  180. this.x509AttrCerts = attributeCertificates;
  181. }
  182. public void SetCertificates(IStore<X509Certificate> certificates)
  183. {
  184. this.x509Certs = certificates;
  185. }
  186. public void SetCrls(IStore<X509Crl> crls)
  187. {
  188. this.x509Crls = crls;
  189. }
  190. public void SetAccuracySeconds(
  191. int accuracySeconds)
  192. {
  193. this.accuracySeconds = accuracySeconds;
  194. }
  195. public void SetAccuracyMillis(
  196. int accuracyMillis)
  197. {
  198. this.accuracyMillis = accuracyMillis;
  199. }
  200. public void SetAccuracyMicros(
  201. int accuracyMicros)
  202. {
  203. this.accuracyMicros = accuracyMicros;
  204. }
  205. public void SetOrdering(
  206. bool ordering)
  207. {
  208. this.ordering = ordering;
  209. }
  210. public void SetTsa(
  211. GeneralName tsa)
  212. {
  213. this.tsa = tsa;
  214. }
  215. //------------------------------------------------------------------------------
  216. public TimeStampToken Generate(
  217. TimeStampRequest request,
  218. BigInteger serialNumber,
  219. DateTime genTime)
  220. {
  221. return Generate(request, serialNumber, genTime, null);
  222. }
  223. public TimeStampToken Generate(
  224. TimeStampRequest request,
  225. BigInteger serialNumber,
  226. DateTime genTime, X509Extensions additionalExtensions)
  227. {
  228. DerObjectIdentifier digestAlgOID = new DerObjectIdentifier(request.MessageImprintAlgOid);
  229. AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DerNull.Instance);
  230. MessageImprint messageImprint = new MessageImprint(algID, request.GetMessageImprintDigest());
  231. Accuracy accuracy = null;
  232. if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0)
  233. {
  234. DerInteger seconds = null;
  235. if (accuracySeconds > 0)
  236. {
  237. seconds = new DerInteger(accuracySeconds);
  238. }
  239. DerInteger millis = null;
  240. if (accuracyMillis > 0)
  241. {
  242. millis = new DerInteger(accuracyMillis);
  243. }
  244. DerInteger micros = null;
  245. if (accuracyMicros > 0)
  246. {
  247. micros = new DerInteger(accuracyMicros);
  248. }
  249. accuracy = new Accuracy(seconds, millis, micros);
  250. }
  251. DerBoolean derOrdering = null;
  252. if (ordering)
  253. {
  254. derOrdering = DerBoolean.GetInstance(ordering);
  255. }
  256. DerInteger nonce = null;
  257. if (request.Nonce != null)
  258. {
  259. nonce = new DerInteger(request.Nonce);
  260. }
  261. DerObjectIdentifier tsaPolicy = tsaPolicyOID;
  262. if (request.ReqPolicy != null)
  263. {
  264. tsaPolicy = new DerObjectIdentifier(request.ReqPolicy);
  265. }
  266. if (tsaPolicy == null)
  267. {
  268. throw new TspValidationException("request contains no policy", PkiFailureInfo.UnacceptedPolicy);
  269. }
  270. X509Extensions respExtensions = request.Extensions;
  271. if (additionalExtensions != null)
  272. {
  273. X509ExtensionsGenerator extGen = new X509ExtensionsGenerator();
  274. if (respExtensions != null)
  275. {
  276. foreach(object oid in respExtensions.ExtensionOids)
  277. {
  278. DerObjectIdentifier id = DerObjectIdentifier.GetInstance(oid);
  279. extGen.AddExtension(id, respExtensions.GetExtension(DerObjectIdentifier.GetInstance(id)));
  280. }
  281. }
  282. foreach (object oid in additionalExtensions.ExtensionOids)
  283. {
  284. DerObjectIdentifier id = DerObjectIdentifier.GetInstance(oid);
  285. extGen.AddExtension(id, additionalExtensions.GetExtension(DerObjectIdentifier.GetInstance(id)));
  286. }
  287. respExtensions = extGen.Generate();
  288. }
  289. var timeStampTime = new Asn1GeneralizedTime(WithResolution(genTime, resolution));
  290. TstInfo tstInfo = new TstInfo(tsaPolicy, messageImprint,
  291. new DerInteger(serialNumber), timeStampTime, accuracy,
  292. derOrdering, nonce, tsa, respExtensions);
  293. try
  294. {
  295. CmsSignedDataGenerator signedDataGenerator = new CmsSignedDataGenerator();
  296. byte[] derEncodedTstInfo = tstInfo.GetDerEncoded();
  297. if (request.CertReq)
  298. {
  299. signedDataGenerator.AddCertificates(x509Certs);
  300. signedDataGenerator.AddAttributeCertificates(x509AttrCerts);
  301. }
  302. signedDataGenerator.AddCrls(x509Crls);
  303. signedDataGenerator.AddSignerInfoGenerator(signerInfoGenerator);
  304. CmsSignedData signedData = signedDataGenerator.Generate(
  305. PkcsObjectIdentifiers.IdCTTstInfo.Id,
  306. new CmsProcessableByteArray(derEncodedTstInfo),
  307. true);
  308. return new TimeStampToken(signedData);
  309. }
  310. catch (CmsException cmsEx)
  311. {
  312. throw new TspException("Error generating time-stamp token", cmsEx);
  313. }
  314. catch (IOException e)
  315. {
  316. throw new TspException("Exception encoding info", e);
  317. }
  318. //catch (InvalidAlgorithmParameterException e)
  319. //{
  320. // throw new TspException("Exception handling CertStore CRLs", e);
  321. //}
  322. }
  323. private static DateTime WithResolution(DateTime dateTime, Resolution resolution)
  324. {
  325. switch (resolution)
  326. {
  327. case Resolution.R_SECONDS:
  328. return DateTimeUtilities.WithPrecisionSecond(dateTime);
  329. case Resolution.R_TENTHS_OF_SECONDS:
  330. return DateTimeUtilities.WithPrecisionDecisecond(dateTime);
  331. case Resolution.R_HUNDREDTHS_OF_SECONDS:
  332. return DateTimeUtilities.WithPrecisionCentisecond(dateTime);
  333. case Resolution.R_MILLISECONDS:
  334. return DateTimeUtilities.WithPrecisionMillisecond(dateTime);
  335. default:
  336. throw new InvalidOperationException();
  337. }
  338. }
  339. private class TableGen
  340. : CmsAttributeTableGenerator
  341. {
  342. private readonly SignerInfoGenerator infoGen;
  343. private readonly EssCertID essCertID;
  344. public TableGen(SignerInfoGenerator infoGen, EssCertID essCertID)
  345. {
  346. this.infoGen = infoGen;
  347. this.essCertID = essCertID;
  348. }
  349. public Asn1.Cms.AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters)
  350. {
  351. Asn1.Cms.AttributeTable tab = infoGen.signedGen.GetAttributes(parameters);
  352. if (tab[PkcsObjectIdentifiers.IdAASigningCertificate] == null)
  353. {
  354. return tab.Add(PkcsObjectIdentifiers.IdAASigningCertificate, new SigningCertificate(essCertID));
  355. }
  356. return tab;
  357. }
  358. }
  359. private class TableGen2
  360. : CmsAttributeTableGenerator
  361. {
  362. private readonly SignerInfoGenerator infoGen;
  363. private readonly EssCertIDv2 essCertID;
  364. public TableGen2(SignerInfoGenerator infoGen, EssCertIDv2 essCertID)
  365. {
  366. this.infoGen = infoGen;
  367. this.essCertID = essCertID;
  368. }
  369. public Asn1.Cms.AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters)
  370. {
  371. Asn1.Cms.AttributeTable tab = infoGen.signedGen.GetAttributes(parameters);
  372. if (tab[PkcsObjectIdentifiers.IdAASigningCertificateV2] == null)
  373. {
  374. return tab.Add(PkcsObjectIdentifiers.IdAASigningCertificateV2, new SigningCertificateV2(essCertID));
  375. }
  376. return tab;
  377. }
  378. }
  379. }
  380. }
  381. #pragma warning restore
  382. #endif