122 lines
3.7 KiB
C#
122 lines
3.7 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto.Generators;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Math;
|
|
using Org.BouncyCastle.Math.EC;
|
|
using Org.BouncyCastle.Security;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Signers;
|
|
|
|
public class ECNRSigner : IDsaExt, IDsa
|
|
{
|
|
private bool forSigning;
|
|
|
|
private ECKeyParameters key;
|
|
|
|
private SecureRandom random;
|
|
|
|
public virtual string AlgorithmName => "ECNR";
|
|
|
|
public virtual BigInteger Order => key.Parameters.N;
|
|
|
|
public virtual void Init(bool forSigning, ICipherParameters parameters)
|
|
{
|
|
this.forSigning = forSigning;
|
|
if (forSigning)
|
|
{
|
|
if (parameters is ParametersWithRandom)
|
|
{
|
|
ParametersWithRandom parametersWithRandom = (ParametersWithRandom)parameters;
|
|
random = parametersWithRandom.Random;
|
|
parameters = parametersWithRandom.Parameters;
|
|
}
|
|
else
|
|
{
|
|
random = new SecureRandom();
|
|
}
|
|
if (!(parameters is ECPrivateKeyParameters))
|
|
{
|
|
throw new InvalidKeyException("EC private key required for signing");
|
|
}
|
|
key = (ECPrivateKeyParameters)parameters;
|
|
}
|
|
else
|
|
{
|
|
if (!(parameters is ECPublicKeyParameters))
|
|
{
|
|
throw new InvalidKeyException("EC public key required for verification");
|
|
}
|
|
key = (ECPublicKeyParameters)parameters;
|
|
}
|
|
}
|
|
|
|
public virtual BigInteger[] GenerateSignature(byte[] message)
|
|
{
|
|
if (!forSigning)
|
|
{
|
|
throw new InvalidOperationException("not initialised for signing");
|
|
}
|
|
BigInteger order = Order;
|
|
int bitLength = order.BitLength;
|
|
BigInteger bigInteger = new BigInteger(1, message);
|
|
int bitLength2 = bigInteger.BitLength;
|
|
ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)key;
|
|
if (bitLength2 > bitLength)
|
|
{
|
|
throw new DataLengthException("input too large for ECNR key.");
|
|
}
|
|
BigInteger bigInteger2 = null;
|
|
BigInteger bigInteger3 = null;
|
|
AsymmetricCipherKeyPair asymmetricCipherKeyPair;
|
|
do
|
|
{
|
|
ECKeyPairGenerator eCKeyPairGenerator = new ECKeyPairGenerator();
|
|
eCKeyPairGenerator.Init(new ECKeyGenerationParameters(eCPrivateKeyParameters.Parameters, random));
|
|
asymmetricCipherKeyPair = eCKeyPairGenerator.GenerateKeyPair();
|
|
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)asymmetricCipherKeyPair.Public;
|
|
BigInteger bigInteger4 = eCPublicKeyParameters.Q.AffineXCoord.ToBigInteger();
|
|
bigInteger2 = bigInteger4.Add(bigInteger).Mod(order);
|
|
}
|
|
while (bigInteger2.SignValue == 0);
|
|
BigInteger d = eCPrivateKeyParameters.D;
|
|
BigInteger d2 = ((ECPrivateKeyParameters)asymmetricCipherKeyPair.Private).D;
|
|
bigInteger3 = d2.Subtract(bigInteger2.Multiply(d)).Mod(order);
|
|
return new BigInteger[2] { bigInteger2, bigInteger3 };
|
|
}
|
|
|
|
public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
|
|
{
|
|
if (forSigning)
|
|
{
|
|
throw new InvalidOperationException("not initialised for verifying");
|
|
}
|
|
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)key;
|
|
BigInteger n = eCPublicKeyParameters.Parameters.N;
|
|
int bitLength = n.BitLength;
|
|
BigInteger bigInteger = new BigInteger(1, message);
|
|
int bitLength2 = bigInteger.BitLength;
|
|
if (bitLength2 > bitLength)
|
|
{
|
|
throw new DataLengthException("input too large for ECNR key.");
|
|
}
|
|
if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (s.CompareTo(BigInteger.Zero) < 0 || s.CompareTo(n) >= 0)
|
|
{
|
|
return false;
|
|
}
|
|
ECPoint g = eCPublicKeyParameters.Parameters.G;
|
|
ECPoint q = eCPublicKeyParameters.Q;
|
|
ECPoint eCPoint = ECAlgorithms.SumOfTwoMultiplies(g, s, q, r).Normalize();
|
|
if (eCPoint.IsInfinity)
|
|
{
|
|
return false;
|
|
}
|
|
BigInteger n2 = eCPoint.AffineXCoord.ToBigInteger();
|
|
BigInteger bigInteger2 = r.Subtract(n2).Mod(n);
|
|
return bigInteger2.Equals(bigInteger);
|
|
}
|
|
}
|