ECNRSigner.cs 6.6 KB

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