ECDsaSigner
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math.EC.Multiplier;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Signers
{
public class ECDsaSigner : IDsa
{
private static readonly BigInteger Eight = BigInteger.ValueOf(8);
protected readonly IDsaKCalculator kCalculator;
protected ECKeyParameters key;
protected SecureRandom random;
public virtual string AlgorithmName => "ECDSA";
public virtual BigInteger Order => key.Parameters.N;
public ECDsaSigner()
{
kCalculator = new RandomDsaKCalculator();
}
public ECDsaSigner(IDsaKCalculator kCalculator)
{
this.kCalculator = kCalculator;
}
public virtual void Init(bool forSigning, ICipherParameters parameters)
{
SecureRandom provided = null;
if (forSigning) {
ParametersWithRandom parametersWithRandom = parameters as ParametersWithRandom;
if (parametersWithRandom != null) {
provided = parametersWithRandom.Random;
parameters = parametersWithRandom.Parameters;
}
ECPrivateKeyParameters eCPrivateKeyParameters = parameters as ECPrivateKeyParameters;
if (eCPrivateKeyParameters == null)
throw new InvalidKeyException("EC private key required for signing");
key = eCPrivateKeyParameters;
} else {
ECPublicKeyParameters eCPublicKeyParameters = parameters as ECPublicKeyParameters;
if (eCPublicKeyParameters == null)
throw new InvalidKeyException("EC public key required for verification");
key = eCPublicKeyParameters;
}
random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, provided);
}
public virtual BigInteger[] GenerateSignature(byte[] message)
{
ECDomainParameters parameters = key.Parameters;
BigInteger n = parameters.N;
BigInteger bigInteger = CalculateE(n, message);
BigInteger d = ((ECPrivateKeyParameters)key).D;
if (kCalculator.IsDeterministic)
kCalculator.Init(n, d, message);
else
kCalculator.Init(n, random);
ECMultiplier eCMultiplier = CreateBasePointMultiplier();
BigInteger bigInteger3;
BigInteger bigInteger4;
while (true) {
BigInteger bigInteger2 = kCalculator.NextK();
bigInteger3 = eCMultiplier.Multiply(parameters.G, bigInteger2).Normalize().AffineXCoord.ToBigInteger().Mod(n);
if (bigInteger3.SignValue != 0) {
bigInteger4 = BigIntegers.ModOddInverse(n, bigInteger2).Multiply(bigInteger.Add(d.Multiply(bigInteger3))).Mod(n);
if (bigInteger4.SignValue != 0)
break;
}
}
return new BigInteger[2] {
bigInteger3,
bigInteger4
};
}
public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
{
BigInteger n = key.Parameters.N;
if (r.SignValue < 1 || s.SignValue < 1 || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0)
return false;
BigInteger bigInteger = CalculateE(n, message);
BigInteger val = BigIntegers.ModOddInverseVar(n, s);
BigInteger a = bigInteger.Multiply(val).Mod(n);
BigInteger b = r.Multiply(val).Mod(n);
ECPoint g = key.Parameters.G;
ECPoint q = ((ECPublicKeyParameters)key).Q;
ECPoint eCPoint = ECAlgorithms.SumOfTwoMultiplies(g, a, q, b);
if (eCPoint.IsInfinity)
return false;
ECCurve curve = eCPoint.Curve;
if (curve != null) {
BigInteger cofactor = curve.Cofactor;
if (cofactor != null && cofactor.CompareTo(Eight) <= 0) {
ECFieldElement denominator = GetDenominator(curve.CoordinateSystem, eCPoint);
if (denominator != null && !denominator.IsZero) {
ECFieldElement xCoord = eCPoint.XCoord;
while (curve.IsValidFieldElement(r)) {
if (curve.FromBigInteger(r).Multiply(denominator).Equals(xCoord))
return true;
r = r.Add(n);
}
return false;
}
}
}
return eCPoint.Normalize().AffineXCoord.ToBigInteger().Mod(n).Equals(r);
}
protected virtual BigInteger CalculateE(BigInteger n, byte[] message)
{
int num = message.Length * 8;
BigInteger bigInteger = new BigInteger(1, message);
if (n.BitLength < num)
bigInteger = bigInteger.ShiftRight(num - n.BitLength);
return bigInteger;
}
protected virtual ECMultiplier CreateBasePointMultiplier()
{
return new FixedPointCombMultiplier();
}
protected virtual ECFieldElement GetDenominator(int coordinateSystem, ECPoint p)
{
switch (coordinateSystem) {
case 1:
case 6:
case 7:
return p.GetZCoord(0);
case 2:
case 3:
case 4:
return p.GetZCoord(0).Square();
default:
return null;
}
}
protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided)
{
if (needed)
return CryptoServicesRegistrar.GetSecureRandom(provided);
return null;
}
}
}