Asn1Signature.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using Org.BouncyCastle.Asn1;
  6. using Org.BouncyCastle.Asn1.CryptoPro;
  7. using Org.BouncyCastle.Asn1.Nist;
  8. using Org.BouncyCastle.Asn1.Oiw;
  9. using Org.BouncyCastle.Asn1.Pkcs;
  10. using Org.BouncyCastle.Asn1.TeleTrust;
  11. using Org.BouncyCastle.Asn1.X509;
  12. using Org.BouncyCastle.Asn1.X9;
  13. using Org.BouncyCastle.Crypto.Parameters;
  14. using Org.BouncyCastle.Security;
  15. using Org.BouncyCastle.Utilities;
  16. using Org.BouncyCastle.Utilities.Collections;
  17. namespace Org.BouncyCastle.Crypto.Operators
  18. {
  19. internal class X509Utilities
  20. {
  21. private static readonly Asn1Null derNull = DerNull.Instance;
  22. private static readonly IDictionary algorithms = Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  23. private static readonly IDictionary exParams = Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  24. private static readonly ISet noParams = new HashSet();
  25. static X509Utilities()
  26. {
  27. algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
  28. algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
  29. algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
  30. algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
  31. algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
  32. algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
  33. algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
  34. algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
  35. algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
  36. algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
  37. algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
  38. algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
  39. algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
  40. algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
  41. algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
  42. algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
  43. algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
  44. algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
  45. algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
  46. algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
  47. algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
  48. algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
  49. algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
  50. algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
  51. algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
  52. algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
  53. algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
  54. algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
  55. algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
  56. algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
  57. algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
  58. algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
  59. algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
  60. algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
  61. algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
  62. algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
  63. algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
  64. algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
  65. algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
  66. algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
  67. algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
  68. algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
  69. //
  70. // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
  71. // The parameters field SHALL be NULL for RSA based signature algorithms.
  72. //
  73. noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
  74. noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
  75. noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
  76. noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
  77. noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
  78. noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
  79. noParams.Add(NistObjectIdentifiers.DsaWithSha224);
  80. noParams.Add(NistObjectIdentifiers.DsaWithSha256);
  81. noParams.Add(NistObjectIdentifiers.DsaWithSha384);
  82. noParams.Add(NistObjectIdentifiers.DsaWithSha512);
  83. //
  84. // RFC 4491
  85. //
  86. noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
  87. noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
  88. //
  89. // explicit params
  90. //
  91. AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
  92. exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
  93. AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
  94. exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
  95. AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
  96. exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
  97. AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
  98. exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
  99. AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
  100. exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
  101. }
  102. /**
  103. * Return the digest algorithm using one of the standard JCA string
  104. * representations rather than the algorithm identifier (if possible).
  105. */
  106. private static string GetDigestAlgName(
  107. DerObjectIdentifier digestAlgOID)
  108. {
  109. if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
  110. {
  111. return "MD5";
  112. }
  113. else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
  114. {
  115. return "SHA1";
  116. }
  117. else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
  118. {
  119. return "SHA224";
  120. }
  121. else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
  122. {
  123. return "SHA256";
  124. }
  125. else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
  126. {
  127. return "SHA384";
  128. }
  129. else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
  130. {
  131. return "SHA512";
  132. }
  133. else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
  134. {
  135. return "RIPEMD128";
  136. }
  137. else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
  138. {
  139. return "RIPEMD160";
  140. }
  141. else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
  142. {
  143. return "RIPEMD256";
  144. }
  145. else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
  146. {
  147. return "GOST3411";
  148. }
  149. else
  150. {
  151. return digestAlgOID.Id;
  152. }
  153. }
  154. internal static string GetSignatureName(AlgorithmIdentifier sigAlgId)
  155. {
  156. Asn1Encodable parameters = sigAlgId.Parameters;
  157. if (parameters != null && !derNull.Equals(parameters))
  158. {
  159. if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
  160. {
  161. RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
  162. return GetDigestAlgName(rsaParams.HashAlgorithm.Algorithm) + "withRSAandMGF1";
  163. }
  164. if (sigAlgId.Algorithm.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
  165. {
  166. Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
  167. return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA";
  168. }
  169. }
  170. return sigAlgId.Algorithm.Id;
  171. }
  172. private static RsassaPssParameters CreatePssParams(
  173. AlgorithmIdentifier hashAlgId,
  174. int saltSize)
  175. {
  176. return new RsassaPssParameters(
  177. hashAlgId,
  178. new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
  179. new DerInteger(saltSize),
  180. new DerInteger(1));
  181. }
  182. internal static DerObjectIdentifier GetAlgorithmOid(
  183. string algorithmName)
  184. {
  185. algorithmName = Org.BouncyCastle.Utilities.Platform.ToUpperInvariant(algorithmName);
  186. if (algorithms.Contains(algorithmName))
  187. {
  188. return (DerObjectIdentifier) algorithms[algorithmName];
  189. }
  190. return new DerObjectIdentifier(algorithmName);
  191. }
  192. internal static AlgorithmIdentifier GetSigAlgID(
  193. DerObjectIdentifier sigOid,
  194. string algorithmName)
  195. {
  196. if (noParams.Contains(sigOid))
  197. {
  198. return new AlgorithmIdentifier(sigOid);
  199. }
  200. algorithmName = Org.BouncyCastle.Utilities.Platform.ToUpperInvariant(algorithmName);
  201. if (exParams.Contains(algorithmName))
  202. {
  203. return new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
  204. }
  205. return new AlgorithmIdentifier(sigOid, DerNull.Instance);
  206. }
  207. internal static IEnumerable GetAlgNames()
  208. {
  209. return new EnumerableProxy(algorithms.Keys);
  210. }
  211. }
  212. internal class SignerBucket
  213. : Stream
  214. {
  215. protected readonly ISigner signer;
  216. public SignerBucket(
  217. ISigner signer)
  218. {
  219. this.signer = signer;
  220. }
  221. public override int Read(
  222. byte[] buffer,
  223. int offset,
  224. int count)
  225. {
  226. throw new NotImplementedException ();
  227. }
  228. public override int ReadByte()
  229. {
  230. throw new NotImplementedException ();
  231. }
  232. public override void Write(
  233. byte[] buffer,
  234. int offset,
  235. int count)
  236. {
  237. if (count > 0)
  238. {
  239. signer.BlockUpdate(buffer, offset, count);
  240. }
  241. }
  242. public override void WriteByte(
  243. byte b)
  244. {
  245. signer.Update(b);
  246. }
  247. public override bool CanRead
  248. {
  249. get { return false; }
  250. }
  251. public override bool CanWrite
  252. {
  253. get { return true; }
  254. }
  255. public override bool CanSeek
  256. {
  257. get { return false; }
  258. }
  259. public override long Length
  260. {
  261. get { return 0; }
  262. }
  263. public override long Position
  264. {
  265. get { throw new NotImplementedException (); }
  266. set { throw new NotImplementedException (); }
  267. }
  268. public override void Flush()
  269. {
  270. }
  271. public override long Seek(
  272. long offset,
  273. SeekOrigin origin)
  274. {
  275. throw new NotImplementedException ();
  276. }
  277. public override void SetLength(
  278. long length)
  279. {
  280. throw new NotImplementedException ();
  281. }
  282. }
  283. /// <summary>
  284. /// Calculator factory class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
  285. /// signature algorithm details.
  286. /// </summary>
  287. public class Asn1SignatureFactory: ISignatureFactory
  288. {
  289. private readonly AlgorithmIdentifier algID;
  290. private readonly string algorithm;
  291. private readonly AsymmetricKeyParameter privateKey;
  292. private readonly SecureRandom random;
  293. /// <summary>
  294. /// Base constructor.
  295. /// </summary>
  296. /// <param name="algorithm">The name of the signature algorithm to use.</param>
  297. /// <param name="privateKey">The private key to be used in the signing operation.</param>
  298. public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null)
  299. {
  300. }
  301. /// <summary>
  302. /// Constructor which also specifies a source of randomness to be used if one is required.
  303. /// </summary>
  304. /// <param name="algorithm">The name of the signature algorithm to use.</param>
  305. /// <param name="privateKey">The private key to be used in the signing operation.</param>
  306. /// <param name="random">The source of randomness to be used in signature calculation.</param>
  307. public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
  308. {
  309. DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
  310. this.algorithm = algorithm;
  311. this.privateKey = privateKey;
  312. this.random = random;
  313. this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
  314. }
  315. public Object AlgorithmDetails
  316. {
  317. get { return this.algID; }
  318. }
  319. public IStreamCalculator CreateCalculator()
  320. {
  321. ISigner sig = SignerUtilities.GetSigner(algorithm);
  322. if (random != null)
  323. {
  324. sig.Init(true, new ParametersWithRandom(privateKey, random));
  325. }
  326. else
  327. {
  328. sig.Init(true, privateKey);
  329. }
  330. return new SigCalculator(sig);
  331. }
  332. /// <summary>
  333. /// Allows enumeration of the signature names supported by the verifier provider.
  334. /// </summary>
  335. public static IEnumerable SignatureAlgNames
  336. {
  337. get { return X509Utilities.GetAlgNames(); }
  338. }
  339. }
  340. internal class SigCalculator : IStreamCalculator
  341. {
  342. private readonly ISigner sig;
  343. private readonly Stream stream;
  344. internal SigCalculator(ISigner sig)
  345. {
  346. this.sig = sig;
  347. this.stream = new SignerBucket(sig);
  348. }
  349. public Stream Stream
  350. {
  351. get { return stream; }
  352. }
  353. public object GetResult()
  354. {
  355. return new SigResult(sig);
  356. }
  357. }
  358. internal class SigResult : IBlockResult
  359. {
  360. private readonly ISigner sig;
  361. internal SigResult(ISigner sig)
  362. {
  363. this.sig = sig;
  364. }
  365. public byte[] Collect()
  366. {
  367. return sig.GenerateSignature();
  368. }
  369. public int Collect(byte[] destination, int offset)
  370. {
  371. byte[] signature = Collect();
  372. Array.Copy(signature, 0, destination, offset, signature.Length);
  373. return signature.Length;
  374. }
  375. }
  376. /// <summary>
  377. /// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
  378. /// signature algorithm details.
  379. /// </summary>
  380. public class Asn1VerifierFactory: IVerifierFactory
  381. {
  382. private readonly AlgorithmIdentifier algID;
  383. private readonly AsymmetricKeyParameter publicKey;
  384. /// <summary>
  385. /// Base constructor.
  386. /// </summary>
  387. /// <param name="algorithm">The name of the signature algorithm to use.</param>
  388. /// <param name="publicKey">The public key to be used in the verification operation.</param>
  389. public Asn1VerifierFactory (String algorithm, AsymmetricKeyParameter publicKey)
  390. {
  391. DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
  392. this.publicKey = publicKey;
  393. this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
  394. }
  395. public Asn1VerifierFactory (AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
  396. {
  397. this.publicKey = publicKey;
  398. this.algID = algorithm;
  399. }
  400. public Object AlgorithmDetails
  401. {
  402. get { return this.algID; }
  403. }
  404. public IStreamCalculator CreateCalculator()
  405. {
  406. ISigner sig = SignerUtilities.GetSigner(X509Utilities.GetSignatureName(algID));
  407. sig.Init(false, publicKey);
  408. return new VerifierCalculator(sig);
  409. }
  410. }
  411. internal class VerifierCalculator : IStreamCalculator
  412. {
  413. private readonly ISigner sig;
  414. private readonly Stream stream;
  415. internal VerifierCalculator(ISigner sig)
  416. {
  417. this.sig = sig;
  418. this.stream = new SignerBucket(sig);
  419. }
  420. public Stream Stream
  421. {
  422. get { return stream; }
  423. }
  424. public object GetResult()
  425. {
  426. return new VerifierResult(sig);
  427. }
  428. }
  429. internal class VerifierResult : IVerifier
  430. {
  431. private readonly ISigner sig;
  432. internal VerifierResult(ISigner sig)
  433. {
  434. this.sig = sig;
  435. }
  436. public bool IsVerified(byte[] signature)
  437. {
  438. return sig.VerifySignature(signature);
  439. }
  440. public bool IsVerified(byte[] signature, int off, int length)
  441. {
  442. byte[] sigBytes = new byte[length];
  443. Array.Copy(signature, 0, sigBytes, off, sigBytes.Length);
  444. return sig.VerifySignature(signature);
  445. }
  446. }
  447. /// <summary>
  448. /// Provider class which supports dynamic creation of signature verifiers.
  449. /// </summary>
  450. public class Asn1VerifierFactoryProvider: IVerifierFactoryProvider
  451. {
  452. private readonly AsymmetricKeyParameter publicKey;
  453. /// <summary>
  454. /// Base constructor - specify the public key to be used in verification.
  455. /// </summary>
  456. /// <param name="publicKey">The public key to be used in creating verifiers provided by this object.</param>
  457. public Asn1VerifierFactoryProvider(AsymmetricKeyParameter publicKey)
  458. {
  459. this.publicKey = publicKey;
  460. }
  461. public IVerifierFactory CreateVerifierFactory(Object algorithmDetails)
  462. {
  463. return new Asn1VerifierFactory ((AlgorithmIdentifier)algorithmDetails, publicKey);
  464. }
  465. /// <summary>
  466. /// Allows enumeration of the signature names supported by the verifier provider.
  467. /// </summary>
  468. public IEnumerable SignatureAlgNames
  469. {
  470. get { return X509Utilities.GetAlgNames(); }
  471. }
  472. }
  473. }
  474. #endif