ECNRSigner.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC;
  9. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  10. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Signers
  11. {
  12. /**
  13. * EC-NR as described in IEEE 1363-2000
  14. */
  15. public class ECNRSigner
  16. : IDsa
  17. {
  18. private bool forSigning;
  19. private ECKeyParameters key;
  20. private SecureRandom random;
  21. public virtual string AlgorithmName
  22. {
  23. get { return "ECNR"; }
  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))
  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. public virtual BigInteger Order
  51. {
  52. get { return key.Parameters.N; }
  53. }
  54. // Section 7.2.5 ECSP-NR, pg 34
  55. /**
  56. * generate a signature for the given message using the key we were
  57. * initialised with. Generally, the order of the curve should be at
  58. * least as long as the hash of the message of interest, and with
  59. * ECNR it *must* be at least as long.
  60. *
  61. * @param digest the digest to be signed.
  62. * @exception DataLengthException if the digest is longer than the key allows
  63. */
  64. public virtual BigInteger[] GenerateSignature(
  65. byte[] message)
  66. {
  67. if (!this.forSigning)
  68. {
  69. // not properly initilaized... deal with it
  70. throw new InvalidOperationException("not initialised for signing");
  71. }
  72. BigInteger n = Order;
  73. int nBitLength = n.BitLength;
  74. BigInteger e = new BigInteger(1, message);
  75. int eBitLength = e.BitLength;
  76. ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)key;
  77. if (eBitLength > nBitLength)
  78. {
  79. throw new DataLengthException("input too large for ECNR key.");
  80. }
  81. BigInteger r = null;
  82. BigInteger s = null;
  83. AsymmetricCipherKeyPair tempPair;
  84. do // generate r
  85. {
  86. // generate another, but very temporary, key pair using
  87. // the same EC parameters
  88. ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
  89. keyGen.Init(new ECKeyGenerationParameters(privKey.Parameters, this.random));
  90. tempPair = keyGen.GenerateKeyPair();
  91. // BigInteger Vx = tempPair.getPublic().getW().getAffineX();
  92. ECPublicKeyParameters V = (ECPublicKeyParameters) tempPair.Public; // get temp's public key
  93. BigInteger Vx = V.Q.AffineXCoord.ToBigInteger(); // get the point's x coordinate
  94. r = Vx.Add(e).Mod(n);
  95. }
  96. while (r.SignValue == 0);
  97. // generate s
  98. BigInteger x = privKey.D; // private key value
  99. BigInteger u = ((ECPrivateKeyParameters) tempPair.Private).D; // temp's private key value
  100. s = u.Subtract(r.Multiply(x)).Mod(n);
  101. return new BigInteger[]{ r, s };
  102. }
  103. // Section 7.2.6 ECVP-NR, pg 35
  104. /**
  105. * return true if the value r and s represent a signature for the
  106. * message passed in. Generally, the order of the curve should be at
  107. * least as long as the hash of the message of interest, and with
  108. * ECNR, it *must* be at least as long. But just in case the signer
  109. * applied mod(n) to the longer digest, this implementation will
  110. * apply mod(n) during verification.
  111. *
  112. * @param digest the digest to be verified.
  113. * @param r the r value of the signature.
  114. * @param s the s value of the signature.
  115. * @exception DataLengthException if the digest is longer than the key allows
  116. */
  117. public virtual bool VerifySignature(
  118. byte[] message,
  119. BigInteger r,
  120. BigInteger s)
  121. {
  122. if (this.forSigning)
  123. {
  124. // not properly initilaized... deal with it
  125. throw new InvalidOperationException("not initialised for verifying");
  126. }
  127. ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key;
  128. BigInteger n = pubKey.Parameters.N;
  129. int nBitLength = n.BitLength;
  130. BigInteger e = new BigInteger(1, message);
  131. int eBitLength = e.BitLength;
  132. if (eBitLength > nBitLength)
  133. {
  134. throw new DataLengthException("input too large for ECNR key.");
  135. }
  136. // r in the range [1,n-1]
  137. if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
  138. {
  139. return false;
  140. }
  141. // s in the range [0,n-1] NB: ECNR spec says 0
  142. if (s.CompareTo(BigInteger.Zero) < 0 || s.CompareTo(n) >= 0)
  143. {
  144. return false;
  145. }
  146. // compute P = sG + rW
  147. ECPoint G = pubKey.Parameters.G;
  148. ECPoint W = pubKey.Q;
  149. // calculate P using Bouncy math
  150. ECPoint P = ECAlgorithms.SumOfTwoMultiplies(G, s, W, r).Normalize();
  151. if (P.IsInfinity)
  152. return false;
  153. BigInteger x = P.AffineXCoord.ToBigInteger();
  154. BigInteger t = r.Subtract(x).Mod(n);
  155. return t.Equals(e);
  156. }
  157. }
  158. }
  159. #pragma warning restore
  160. #endif