ECNRSigner.cs 6.3 KB

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