GOST3410DigestSigner.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Signers
  8. {
  9. public class Gost3410DigestSigner
  10. : ISigner
  11. {
  12. private readonly IDigest digest;
  13. private readonly IDsa dsaSigner;
  14. private readonly int size;
  15. private int halfSize;
  16. private bool forSigning;
  17. public Gost3410DigestSigner(IDsa signer, IDigest digest)
  18. {
  19. this.dsaSigner = signer;
  20. this.digest = digest;
  21. halfSize = digest.GetDigestSize();
  22. this.size = halfSize * 2;
  23. }
  24. public virtual string AlgorithmName
  25. {
  26. get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
  27. }
  28. public virtual void Init(bool forSigning, ICipherParameters parameters)
  29. {
  30. this.forSigning = forSigning;
  31. AsymmetricKeyParameter k;
  32. if (parameters is ParametersWithRandom)
  33. {
  34. k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
  35. }
  36. else
  37. {
  38. k = (AsymmetricKeyParameter)parameters;
  39. }
  40. if (forSigning && !k.IsPrivate)
  41. {
  42. throw new InvalidKeyException("Signing Requires Private Key.");
  43. }
  44. if (!forSigning && k.IsPrivate)
  45. {
  46. throw new InvalidKeyException("Verification Requires Public Key.");
  47. }
  48. Reset();
  49. dsaSigner.Init(forSigning, parameters);
  50. }
  51. public virtual void Update(byte input)
  52. {
  53. digest.Update(input);
  54. }
  55. public virtual void BlockUpdate(byte[] input, int inOff, int inLen)
  56. {
  57. digest.BlockUpdate(input, inOff, inLen);
  58. }
  59. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  60. public virtual void BlockUpdate(ReadOnlySpan<byte> input)
  61. {
  62. digest.BlockUpdate(input);
  63. }
  64. #endif
  65. public virtual byte[] GenerateSignature()
  66. {
  67. if (!forSigning)
  68. throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation.");
  69. byte[] hash = new byte[digest.GetDigestSize()];
  70. digest.DoFinal(hash, 0);
  71. try
  72. {
  73. BigInteger[] sig = dsaSigner.GenerateSignature(hash);
  74. byte[] sigBytes = new byte[size];
  75. // TODO Add methods to allow writing BigInteger to existing byte array?
  76. byte[] r = sig[0].ToByteArrayUnsigned();
  77. byte[] s = sig[1].ToByteArrayUnsigned();
  78. s.CopyTo(sigBytes, halfSize - s.Length);
  79. r.CopyTo(sigBytes, size - r.Length);
  80. return sigBytes;
  81. }
  82. catch (Exception e)
  83. {
  84. throw new SignatureException(e.Message, e);
  85. }
  86. }
  87. public virtual bool VerifySignature(byte[] signature)
  88. {
  89. if (forSigning)
  90. throw new InvalidOperationException("DSADigestSigner not initialised for verification");
  91. byte[] hash = new byte[digest.GetDigestSize()];
  92. digest.DoFinal(hash, 0);
  93. BigInteger R, S;
  94. try
  95. {
  96. R = new BigInteger(1, signature, halfSize, halfSize);
  97. S = new BigInteger(1, signature, 0, halfSize);
  98. }
  99. catch (Exception e)
  100. {
  101. throw new SignatureException("error decoding signature bytes.", e);
  102. }
  103. return dsaSigner.VerifySignature(hash, R, S);
  104. }
  105. public virtual void Reset()
  106. {
  107. digest.Reset();
  108. }
  109. }
  110. }
  111. #pragma warning restore
  112. #endif