TimeStampToken.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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.Ess;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Tsp;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Cms;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  17. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509;
  18. using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Store;
  19. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tsp
  20. {
  21. public class TimeStampToken
  22. {
  23. private readonly CmsSignedData tsToken;
  24. private readonly SignerInformation tsaSignerInfo;
  25. // private readonly DateTime genTime;
  26. private readonly TimeStampTokenInfo tstInfo;
  27. private readonly CertID certID;
  28. public TimeStampToken(
  29. Asn1.Cms.ContentInfo contentInfo)
  30. : this(new CmsSignedData(contentInfo))
  31. {
  32. }
  33. public TimeStampToken(
  34. CmsSignedData signedData)
  35. {
  36. this.tsToken = signedData;
  37. if (!this.tsToken.SignedContentType.Equals(PkcsObjectIdentifiers.IdCTTstInfo))
  38. {
  39. throw new TspValidationException("ContentInfo object not for a time stamp.");
  40. }
  41. ICollection signers = tsToken.GetSignerInfos().GetSigners();
  42. if (signers.Count != 1)
  43. {
  44. throw new ArgumentException("Time-stamp token signed by "
  45. + signers.Count
  46. + " signers, but it must contain just the TSA signature.");
  47. }
  48. IEnumerator signerEnum = signers.GetEnumerator();
  49. signerEnum.MoveNext();
  50. tsaSignerInfo = (SignerInformation) signerEnum.Current;
  51. try
  52. {
  53. CmsProcessable content = tsToken.SignedContent;
  54. MemoryStream bOut = new MemoryStream();
  55. content.Write(bOut);
  56. this.tstInfo = new TimeStampTokenInfo(
  57. TstInfo.GetInstance(
  58. Asn1Object.FromByteArray(bOut.ToArray())));
  59. Asn1.Cms.Attribute attr = tsaSignerInfo.SignedAttributes[
  60. PkcsObjectIdentifiers.IdAASigningCertificate];
  61. // if (attr == null)
  62. // {
  63. // throw new TspValidationException(
  64. // "no signing certificate attribute found, time stamp invalid.");
  65. // }
  66. //
  67. // SigningCertificate signCert = SigningCertificate.GetInstance(
  68. // attr.AttrValues[0]);
  69. //
  70. // this.certID = EssCertID.GetInstance(signCert.GetCerts()[0]);
  71. if (attr != null)
  72. {
  73. if (attr.AttrValues[0] is SigningCertificateV2)
  74. {
  75. SigningCertificateV2 signCert = SigningCertificateV2.GetInstance(attr.AttrValues[0]);
  76. this.certID = new CertID(EssCertIDv2.GetInstance(signCert.GetCerts()[0]));
  77. }
  78. else
  79. {
  80. SigningCertificate signCert = SigningCertificate.GetInstance(attr.AttrValues[0]);
  81. this.certID = new CertID(EssCertID.GetInstance(signCert.GetCerts()[0]));
  82. }
  83. }
  84. else
  85. {
  86. attr = tsaSignerInfo.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificateV2];
  87. if (attr == null)
  88. throw new TspValidationException("no signing certificate attribute found, time stamp invalid.");
  89. SigningCertificateV2 signCertV2 = SigningCertificateV2.GetInstance(attr.AttrValues[0]);
  90. this.certID = new CertID(EssCertIDv2.GetInstance(signCertV2.GetCerts()[0]));
  91. }
  92. }
  93. catch (CmsException e)
  94. {
  95. throw new TspException(e.Message, e.InnerException);
  96. }
  97. }
  98. public TimeStampTokenInfo TimeStampInfo
  99. {
  100. get { return tstInfo; }
  101. }
  102. public SignerID SignerID
  103. {
  104. get { return tsaSignerInfo.SignerID; }
  105. }
  106. public Asn1.Cms.AttributeTable SignedAttributes
  107. {
  108. get { return tsaSignerInfo.SignedAttributes; }
  109. }
  110. public Asn1.Cms.AttributeTable UnsignedAttributes
  111. {
  112. get { return tsaSignerInfo.UnsignedAttributes; }
  113. }
  114. public IX509Store GetCertificates(
  115. string type)
  116. {
  117. return tsToken.GetCertificates(type);
  118. }
  119. public IX509Store GetCrls(
  120. string type)
  121. {
  122. return tsToken.GetCrls(type);
  123. }
  124. public IX509Store GetCertificates()
  125. {
  126. return tsToken.GetCertificates();
  127. }
  128. public IX509Store GetAttributeCertificates(
  129. string type)
  130. {
  131. return tsToken.GetAttributeCertificates(type);
  132. }
  133. /**
  134. * Validate the time stamp token.
  135. * <p>
  136. * To be valid the token must be signed by the passed in certificate and
  137. * the certificate must be the one referred to by the SigningCertificate
  138. * attribute included in the hashed attributes of the token. The
  139. * certificate must also have the ExtendedKeyUsageExtension with only
  140. * KeyPurposeID.IdKPTimeStamping and have been valid at the time the
  141. * timestamp was created.
  142. * </p>
  143. * <p>
  144. * A successful call to validate means all the above are true.
  145. * </p>
  146. */
  147. public void Validate(
  148. X509Certificate cert)
  149. {
  150. try
  151. {
  152. byte[] hash = DigestUtilities.CalculateDigest(
  153. certID.GetHashAlgorithmName(), cert.GetEncoded());
  154. if (!Arrays.ConstantTimeAreEqual(certID.GetCertHash(), hash))
  155. throw new TspValidationException("certificate hash does not match certID hash.");
  156. if (certID.IssuerSerial != null)
  157. {
  158. if (!certID.IssuerSerial.Serial.HasValue(cert.SerialNumber))
  159. throw new TspValidationException("certificate serial number does not match certID for signature.");
  160. GeneralName[] names = certID.IssuerSerial.Issuer.GetNames();
  161. X509Name principal = PrincipalUtilities.GetIssuerX509Principal(cert);
  162. bool found = false;
  163. for (int i = 0; i != names.Length; i++)
  164. {
  165. if (names[i].TagNo == 4
  166. && X509Name.GetInstance(names[i].Name).Equivalent(principal))
  167. {
  168. found = true;
  169. break;
  170. }
  171. }
  172. if (!found)
  173. {
  174. throw new TspValidationException("certificate name does not match certID for signature. ");
  175. }
  176. }
  177. TspUtil.ValidateCertificate(cert);
  178. cert.CheckValidity(tstInfo.GenTime);
  179. if (!tsaSignerInfo.Verify(cert))
  180. {
  181. throw new TspValidationException("signature not created by certificate.");
  182. }
  183. }
  184. catch (CmsException e)
  185. {
  186. if (e.InnerException != null)
  187. {
  188. throw new TspException(e.Message, e.InnerException);
  189. }
  190. throw new TspException("CMS exception: " + e, e);
  191. }
  192. catch (CertificateEncodingException e)
  193. {
  194. throw new TspException("problem processing certificate: " + e, e);
  195. }
  196. catch (SecurityUtilityException e)
  197. {
  198. throw new TspException("cannot find algorithm: " + e.Message, e);
  199. }
  200. }
  201. /**
  202. * Return the underlying CmsSignedData object.
  203. *
  204. * @return the underlying CMS structure.
  205. */
  206. public CmsSignedData ToCmsSignedData()
  207. {
  208. return tsToken;
  209. }
  210. /**
  211. * Return a ASN.1 encoded byte stream representing the encoded object.
  212. *
  213. * @throws IOException if encoding fails.
  214. */
  215. public byte[] GetEncoded()
  216. {
  217. return tsToken.GetEncoded(Asn1Encodable.Der);
  218. }
  219. /**
  220. * return the ASN.1 encoded representation of this object using the specified encoding.
  221. *
  222. * @param encoding the ASN.1 encoding format to use ("BER" or "DER").
  223. */
  224. public byte[] GetEncoded(string encoding)
  225. {
  226. return tsToken.GetEncoded(encoding);
  227. }
  228. // perhaps this should be done using an interface on the ASN.1 classes...
  229. private class CertID
  230. {
  231. private EssCertID certID;
  232. private EssCertIDv2 certIDv2;
  233. internal CertID(EssCertID certID)
  234. {
  235. this.certID = certID;
  236. this.certIDv2 = null;
  237. }
  238. internal CertID(EssCertIDv2 certID)
  239. {
  240. this.certIDv2 = certID;
  241. this.certID = null;
  242. }
  243. public string GetHashAlgorithmName()
  244. {
  245. if (certID != null)
  246. return "SHA-1";
  247. if (NistObjectIdentifiers.IdSha256.Equals(certIDv2.HashAlgorithm.Algorithm))
  248. return "SHA-256";
  249. return certIDv2.HashAlgorithm.Algorithm.Id;
  250. }
  251. public AlgorithmIdentifier GetHashAlgorithm()
  252. {
  253. return (certID != null)
  254. ? new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1)
  255. : certIDv2.HashAlgorithm;
  256. }
  257. public byte[] GetCertHash()
  258. {
  259. return certID != null
  260. ? certID.GetCertHash()
  261. : certIDv2.GetCertHash();
  262. }
  263. public IssuerSerial IssuerSerial
  264. {
  265. get
  266. {
  267. return certID != null
  268. ? certID.IssuerSerial
  269. : certIDv2.IssuerSerial;
  270. }
  271. }
  272. }
  273. }
  274. }
  275. #pragma warning restore
  276. #endif