TSPUtil.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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.CryptoPro;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.GM;
  9. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
  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.Rosstandart;
  13. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.TeleTrust;
  14. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  15. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Cms;
  16. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  17. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  18. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  19. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  20. using Best.HTTP.SecureProtocol.Org.BouncyCastle.X509;
  21. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tsp
  22. {
  23. public class TspUtil
  24. {
  25. private static readonly Dictionary<string, int> DigestLengths = new Dictionary<string, int>();
  26. private static readonly Dictionary<string, string> DigestNames = new Dictionary<string, string>();
  27. static TspUtil()
  28. {
  29. DigestLengths.Add(PkcsObjectIdentifiers.MD5.Id, 16);
  30. DigestLengths.Add(OiwObjectIdentifiers.IdSha1.Id, 20);
  31. DigestLengths.Add(NistObjectIdentifiers.IdSha224.Id, 28);
  32. DigestLengths.Add(NistObjectIdentifiers.IdSha256.Id, 32);
  33. DigestLengths.Add(NistObjectIdentifiers.IdSha384.Id, 48);
  34. DigestLengths.Add(NistObjectIdentifiers.IdSha512.Id, 64);
  35. DigestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, 16);
  36. DigestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, 20);
  37. DigestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, 32);
  38. DigestLengths.Add(CryptoProObjectIdentifiers.GostR3411.Id, 32);
  39. DigestLengths.Add(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256.Id, 32);
  40. DigestLengths.Add(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512.Id, 64);
  41. DigestLengths.Add(GMObjectIdentifiers.sm3.Id, 32);
  42. DigestNames.Add(PkcsObjectIdentifiers.MD5.Id, "MD5");
  43. DigestNames.Add(OiwObjectIdentifiers.IdSha1.Id, "SHA1");
  44. DigestNames.Add(NistObjectIdentifiers.IdSha224.Id, "SHA224");
  45. DigestNames.Add(NistObjectIdentifiers.IdSha256.Id, "SHA256");
  46. DigestNames.Add(NistObjectIdentifiers.IdSha384.Id, "SHA384");
  47. DigestNames.Add(NistObjectIdentifiers.IdSha512.Id, "SHA512");
  48. DigestNames.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption.Id, "MD5");
  49. DigestNames.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id, "SHA1");
  50. DigestNames.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption.Id, "SHA224");
  51. DigestNames.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, "SHA256");
  52. DigestNames.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id, "SHA384");
  53. DigestNames.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id, "SHA512");
  54. DigestNames.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, "RIPEMD128");
  55. DigestNames.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, "RIPEMD160");
  56. DigestNames.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, "RIPEMD256");
  57. DigestNames.Add(CryptoProObjectIdentifiers.GostR3411.Id, "GOST3411");
  58. DigestNames.Add(OiwObjectIdentifiers.DsaWithSha1.Id, "SHA1");
  59. DigestNames.Add(OiwObjectIdentifiers.Sha1WithRsa.Id, "SHA1");
  60. DigestNames.Add(OiwObjectIdentifiers.MD5WithRsa.Id, "MD5");
  61. DigestNames.Add(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256.Id, "GOST3411-2012-256");
  62. DigestNames.Add(RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512.Id, "GOST3411-2012-512");
  63. DigestNames.Add(GMObjectIdentifiers.sm3.Id, "SM3");
  64. }
  65. /**
  66. * Fetches the signature time-stamp attributes from a SignerInformation object.
  67. * Checks that the MessageImprint for each time-stamp matches the signature field.
  68. * (see RFC 3161 Appendix A).
  69. *
  70. * @param signerInfo a SignerInformation to search for time-stamps
  71. * @return a collection of TimeStampToken objects
  72. * @throws TSPValidationException
  73. */
  74. public static IList<TimeStampToken> GetSignatureTimestamps(
  75. SignerInformation signerInfo)
  76. {
  77. var timestamps = new List<TimeStampToken>();
  78. Asn1.Cms.AttributeTable unsignedAttrs = signerInfo.UnsignedAttributes;
  79. if (unsignedAttrs != null)
  80. {
  81. foreach (Asn1.Cms.Attribute tsAttr in unsignedAttrs.GetAll(
  82. PkcsObjectIdentifiers.IdAASignatureTimeStampToken))
  83. {
  84. foreach (Asn1Encodable asn1 in tsAttr.AttrValues)
  85. {
  86. try
  87. {
  88. Asn1.Cms.ContentInfo contentInfo = Asn1.Cms.ContentInfo.GetInstance(
  89. asn1.ToAsn1Object());
  90. TimeStampToken timeStampToken = new TimeStampToken(contentInfo);
  91. TimeStampTokenInfo tstInfo = timeStampToken.TimeStampInfo;
  92. byte[] expectedDigest = DigestUtilities.CalculateDigest(
  93. GetDigestAlgName(tstInfo.MessageImprintAlgOid),
  94. signerInfo.GetSignature());
  95. if (!Arrays.ConstantTimeAreEqual(expectedDigest, tstInfo.GetMessageImprintDigest()))
  96. throw new TspValidationException("Incorrect digest in message imprint");
  97. timestamps.Add(timeStampToken);
  98. }
  99. catch (SecurityUtilityException)
  100. {
  101. throw new TspValidationException("Unknown hash algorithm specified in timestamp");
  102. }
  103. catch (Exception)
  104. {
  105. throw new TspValidationException("Timestamp could not be parsed");
  106. }
  107. }
  108. }
  109. }
  110. return timestamps;
  111. }
  112. /**
  113. * Validate the passed in certificate as being of the correct type to be used
  114. * for time stamping. To be valid it must have an ExtendedKeyUsage extension
  115. * which has a key purpose identifier of id-kp-timeStamping.
  116. *
  117. * @param cert the certificate of interest.
  118. * @throws TspValidationException if the certicate fails on one of the check points.
  119. */
  120. public static void ValidateCertificate(
  121. X509Certificate cert)
  122. {
  123. if (cert.Version != 3)
  124. throw new ArgumentException("Certificate must have an ExtendedKeyUsage extension.");
  125. Asn1OctetString ext = cert.GetExtensionValue(X509Extensions.ExtendedKeyUsage);
  126. if (ext == null)
  127. throw new TspValidationException("Certificate must have an ExtendedKeyUsage extension.");
  128. if (!cert.GetCriticalExtensionOids().Contains(X509Extensions.ExtendedKeyUsage.Id))
  129. throw new TspValidationException("Certificate must have an ExtendedKeyUsage extension marked as critical.");
  130. try
  131. {
  132. ExtendedKeyUsage extKey = ExtendedKeyUsage.GetInstance(
  133. Asn1Object.FromByteArray(ext.GetOctets()));
  134. if (!extKey.HasKeyPurposeId(KeyPurposeID.id_kp_timeStamping) || extKey.Count != 1)
  135. throw new TspValidationException("ExtendedKeyUsage not solely time stamping.");
  136. }
  137. catch (IOException)
  138. {
  139. throw new TspValidationException("cannot process ExtendedKeyUsage extension");
  140. }
  141. }
  142. /// <summary>
  143. /// Return the digest algorithm using one of the standard JCA string
  144. /// representations rather than the algorithm identifier (if possible).
  145. /// </summary>
  146. internal static string GetDigestAlgName(string digestAlgOid)
  147. {
  148. return CollectionUtilities.GetValueOrKey(DigestNames, digestAlgOid);
  149. }
  150. internal static int GetDigestLength(string digestAlgOid)
  151. {
  152. if (!DigestLengths.TryGetValue(digestAlgOid, out int length))
  153. throw new TspException("digest algorithm cannot be found.");
  154. return length;
  155. }
  156. internal static IDigest CreateDigestInstance(string digestAlgOID)
  157. {
  158. string digestName = GetDigestAlgName(digestAlgOID);
  159. return DigestUtilities.GetDigest(digestName);
  160. }
  161. internal static ISet<DerObjectIdentifier> GetCriticalExtensionOids(X509Extensions extensions)
  162. {
  163. return extensions == null
  164. ? new HashSet<DerObjectIdentifier>()
  165. : new HashSet<DerObjectIdentifier>(extensions.GetCriticalExtensionOids());
  166. }
  167. internal static ISet<DerObjectIdentifier> GetNonCriticalExtensionOids(X509Extensions extensions)
  168. {
  169. return extensions == null
  170. ? new HashSet<DerObjectIdentifier>()
  171. : new HashSet<DerObjectIdentifier>(extensions.GetNonCriticalExtensionOids());
  172. }
  173. internal static IList<DerObjectIdentifier> GetExtensionOids(X509Extensions extensions)
  174. {
  175. return extensions == null
  176. ? new List<DerObjectIdentifier>()
  177. : new List<DerObjectIdentifier>(extensions.GetExtensionOids());
  178. }
  179. }
  180. }
  181. #pragma warning restore
  182. #endif