121 lines
3.1 KiB
C#
121 lines
3.1 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Math;
|
|
using Org.BouncyCastle.Security;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Signers;
|
|
|
|
public class DsaSigner : IDsaExt, IDsa
|
|
{
|
|
protected readonly IDsaKCalculator kCalculator;
|
|
|
|
protected DsaKeyParameters key = null;
|
|
|
|
protected SecureRandom random = null;
|
|
|
|
public virtual string AlgorithmName => "DSA";
|
|
|
|
public virtual BigInteger Order => key.Parameters.Q;
|
|
|
|
public DsaSigner()
|
|
{
|
|
kCalculator = new RandomDsaKCalculator();
|
|
}
|
|
|
|
public DsaSigner(IDsaKCalculator kCalculator)
|
|
{
|
|
this.kCalculator = kCalculator;
|
|
}
|
|
|
|
public virtual void Init(bool forSigning, ICipherParameters parameters)
|
|
{
|
|
SecureRandom provided = null;
|
|
if (forSigning)
|
|
{
|
|
if (parameters is ParametersWithRandom)
|
|
{
|
|
ParametersWithRandom parametersWithRandom = (ParametersWithRandom)parameters;
|
|
provided = parametersWithRandom.Random;
|
|
parameters = parametersWithRandom.Parameters;
|
|
}
|
|
if (!(parameters is DsaPrivateKeyParameters))
|
|
{
|
|
throw new InvalidKeyException("DSA private key required for signing");
|
|
}
|
|
key = (DsaPrivateKeyParameters)parameters;
|
|
}
|
|
else
|
|
{
|
|
if (!(parameters is DsaPublicKeyParameters))
|
|
{
|
|
throw new InvalidKeyException("DSA public key required for verification");
|
|
}
|
|
key = (DsaPublicKeyParameters)parameters;
|
|
}
|
|
random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, provided);
|
|
}
|
|
|
|
public virtual BigInteger[] GenerateSignature(byte[] message)
|
|
{
|
|
DsaParameters parameters = key.Parameters;
|
|
BigInteger q = parameters.Q;
|
|
BigInteger bigInteger = CalculateE(q, message);
|
|
BigInteger x = ((DsaPrivateKeyParameters)key).X;
|
|
if (kCalculator.IsDeterministic)
|
|
{
|
|
kCalculator.Init(q, x, message);
|
|
}
|
|
else
|
|
{
|
|
kCalculator.Init(q, random);
|
|
}
|
|
BigInteger bigInteger2 = kCalculator.NextK();
|
|
BigInteger bigInteger3 = parameters.G.ModPow(bigInteger2, parameters.P).Mod(q);
|
|
bigInteger2 = bigInteger2.ModInverse(q).Multiply(bigInteger.Add(x.Multiply(bigInteger3)));
|
|
BigInteger bigInteger4 = bigInteger2.Mod(q);
|
|
return new BigInteger[2] { bigInteger3, bigInteger4 };
|
|
}
|
|
|
|
public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
|
|
{
|
|
DsaParameters parameters = key.Parameters;
|
|
BigInteger q = parameters.Q;
|
|
BigInteger bigInteger = CalculateE(q, message);
|
|
if (r.SignValue <= 0 || q.CompareTo(r) <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (s.SignValue <= 0 || q.CompareTo(s) <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
BigInteger val = s.ModInverse(q);
|
|
BigInteger e = bigInteger.Multiply(val).Mod(q);
|
|
BigInteger e2 = r.Multiply(val).Mod(q);
|
|
BigInteger p = parameters.P;
|
|
e = parameters.G.ModPow(e, p);
|
|
e2 = ((DsaPublicKeyParameters)key).Y.ModPow(e2, p);
|
|
BigInteger bigInteger2 = e.Multiply(e2).Mod(p).Mod(q);
|
|
return bigInteger2.Equals(r);
|
|
}
|
|
|
|
protected virtual BigInteger CalculateE(BigInteger n, byte[] message)
|
|
{
|
|
int length = System.Math.Min(message.Length, n.BitLength / 8);
|
|
return new BigInteger(1, message, 0, length);
|
|
}
|
|
|
|
protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided)
|
|
{
|
|
if (needed)
|
|
{
|
|
if (provided == null)
|
|
{
|
|
return new SecureRandom();
|
|
}
|
|
return provided;
|
|
}
|
|
return null;
|
|
}
|
|
}
|