TimeStampTokenGenerator.cs 17 KB

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