ECGOST3410Signer.cs 5.1 KB

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