ECGOST3410Signer.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using Org.BouncyCastle.Crypto;
  4. using Org.BouncyCastle.Crypto.Parameters;
  5. using Org.BouncyCastle.Math;
  6. using Org.BouncyCastle.Math.EC;
  7. using Org.BouncyCastle.Math.EC.Multiplier;
  8. using Org.BouncyCastle.Security;
  9. namespace Org.BouncyCastle.Crypto.Signers
  10. {
  11. /**
  12. * GOST R 34.10-2001 Signature Algorithm
  13. */
  14. public class ECGost3410Signer
  15. : IDsa
  16. {
  17. private ECKeyParameters key;
  18. private SecureRandom random;
  19. public virtual string AlgorithmName
  20. {
  21. get { return "ECGOST3410"; }
  22. }
  23. public virtual void Init(
  24. bool forSigning,
  25. ICipherParameters parameters)
  26. {
  27. if (forSigning)
  28. {
  29. if (parameters is ParametersWithRandom)
  30. {
  31. ParametersWithRandom rParam = (ParametersWithRandom)parameters;
  32. this.random = rParam.Random;
  33. parameters = rParam.Parameters;
  34. }
  35. else
  36. {
  37. this.random = new SecureRandom();
  38. }
  39. if (!(parameters is ECPrivateKeyParameters))
  40. throw new InvalidKeyException("EC private key required for signing");
  41. this.key = (ECPrivateKeyParameters) parameters;
  42. }
  43. else
  44. {
  45. if (!(parameters is ECPublicKeyParameters))
  46. throw new InvalidKeyException("EC public key required for verification");
  47. this.key = (ECPublicKeyParameters)parameters;
  48. }
  49. }
  50. /**
  51. * generate a signature for the given message using the key we were
  52. * initialised with. For conventional GOST3410 the message should be a GOST3411
  53. * hash of the message of interest.
  54. *
  55. * @param message the message that will be verified later.
  56. */
  57. public virtual BigInteger[] GenerateSignature(
  58. byte[] message)
  59. {
  60. byte[] mRev = new byte[message.Length]; // conversion is little-endian
  61. for (int i = 0; i != mRev.Length; i++)
  62. {
  63. mRev[i] = message[mRev.Length - 1 - i];
  64. }
  65. BigInteger e = new BigInteger(1, mRev);
  66. ECDomainParameters ec = key.Parameters;
  67. BigInteger n = ec.N;
  68. BigInteger d = ((ECPrivateKeyParameters)key).D;
  69. BigInteger r, s = null;
  70. ECMultiplier basePointMultiplier = CreateBasePointMultiplier();
  71. do // generate s
  72. {
  73. BigInteger k;
  74. do // generate r
  75. {
  76. do
  77. {
  78. k = new BigInteger(n.BitLength, random);
  79. }
  80. while (k.SignValue == 0);
  81. ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize();
  82. r = p.AffineXCoord.ToBigInteger().Mod(n);
  83. }
  84. while (r.SignValue == 0);
  85. s = (k.Multiply(e)).Add(d.Multiply(r)).Mod(n);
  86. }
  87. while (s.SignValue == 0);
  88. return new BigInteger[]{ r, s };
  89. }
  90. /**
  91. * return true if the value r and s represent a GOST3410 signature for
  92. * the passed in message (for standard GOST3410 the message should be
  93. * a GOST3411 hash of the real message to be verified).
  94. */
  95. public virtual bool VerifySignature(
  96. byte[] message,
  97. BigInteger r,
  98. BigInteger s)
  99. {
  100. byte[] mRev = new byte[message.Length]; // conversion is little-endian
  101. for (int i = 0; i != mRev.Length; i++)
  102. {
  103. mRev[i] = message[mRev.Length - 1 - i];
  104. }
  105. BigInteger e = new BigInteger(1, mRev);
  106. BigInteger n = key.Parameters.N;
  107. // r in the range [1,n-1]
  108. if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
  109. {
  110. return false;
  111. }
  112. // s in the range [1,n-1]
  113. if (s.CompareTo(BigInteger.One) < 0 || s.CompareTo(n) >= 0)
  114. {
  115. return false;
  116. }
  117. BigInteger v = e.ModInverse(n);
  118. BigInteger z1 = s.Multiply(v).Mod(n);
  119. BigInteger z2 = (n.Subtract(r)).Multiply(v).Mod(n);
  120. ECPoint G = key.Parameters.G; // P
  121. ECPoint Q = ((ECPublicKeyParameters)key).Q;
  122. ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2).Normalize();
  123. if (point.IsInfinity)
  124. return false;
  125. BigInteger R = point.AffineXCoord.ToBigInteger().Mod(n);
  126. return R.Equals(r);
  127. }
  128. protected virtual ECMultiplier CreateBasePointMultiplier()
  129. {
  130. return new FixedPointCombMultiplier();
  131. }
  132. }
  133. }
  134. #endif