Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/org/bouncycastle')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java3
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java11
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java16
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java313
9 files changed, 225 insertions, 185 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
index 0e893ea1..a5296830 100644
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
+++ b/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
@@ -7,7 +7,9 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
/**
* this does your basic ElGamal encryption algorithm using EC
@@ -65,8 +67,10 @@ public class ECElGamalEncryptor
ECDomainParameters ec = key.getParameters();
BigInteger k = ECUtil.generateK(ec.getN(), random);
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+
ECPoint[] gamma_phi = new ECPoint[]{
- ec.getG().multiply(k),
+ basePointMultiplier.multiply(ec.getG(), k),
key.getQ().multiply(k).add(point)
};
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
index c382059d..02f5ca37 100644
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
+++ b/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
@@ -5,7 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
/**
* this transforms the original randomness used for an ElGamal encryption by a fixed value.
@@ -39,7 +41,7 @@ public class ECFixedTransform
}
/**
- * Transform an existing cipher test pair using the ElGamal algorithm. Note: it is assumed this
+ * Transform an existing cipher text pair using the ElGamal algorithm. Note: it is assumed this
* transform has been initialised with the same public key that was used to create the original
* cipher text.
*
@@ -54,9 +56,13 @@ public class ECFixedTransform
}
ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+ BigInteger k = this.k.mod(n);
ECPoint[] gamma_phi = new ECPoint[]{
- ec.getG().multiply(k).add(cipherText.getX()),
+ basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()),
key.getQ().multiply(k).add(cipherText.getY())
};
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
index 74016c18..9f7a0bf1 100644
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
+++ b/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
@@ -4,9 +4,12 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
/**
* this does your basic Elgamal encryption algorithm using EC
@@ -49,7 +52,7 @@ public class ECNewPublicKeyTransform
}
/**
- * Transform an existing cipher test pair using the ElGamal algorithm. Note: the input cipherText will
+ * Transform an existing cipher text pair using the ElGamal algorithm. Note: the input cipherText will
* need to be preserved in order to complete the transformation to the new public key.
*
* @param cipherText the EC point to process.
@@ -62,13 +65,19 @@ public class ECNewPublicKeyTransform
throw new IllegalStateException("ECNewPublicKeyTransform not initialised");
}
- BigInteger n = key.getParameters().getN();
- BigInteger k = ECUtil.generateK(n, random);
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
- ECPoint g = key.getParameters().getG();
- ECPoint gamma = g.multiply(k);
- ECPoint phi = key.getQ().multiply(k).add(cipherText.getY());
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+ BigInteger k = ECUtil.generateK(n, random);
- return new ECPair(gamma.normalize(), phi.normalize());
+ ECPoint[] gamma_phi = new ECPoint[]{
+ basePointMultiplier.multiply(ec.getG(), k),
+ key.getQ().multiply(k).add(cipherText.getY())
+ };
+
+ ec.getCurve().normalizeAll(gamma_phi);
+
+ return new ECPair(gamma_phi[0], gamma_phi[1]);
}
}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
index b293759a..c146a0fb 100644
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
+++ b/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
@@ -4,9 +4,12 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
/**
* this transforms the original randomness used for an ElGamal encryption.
@@ -66,16 +69,23 @@ public class ECNewRandomnessTransform
throw new IllegalStateException("ECNewRandomnessTransform not initialised");
}
- BigInteger n = key.getParameters().getN();
- BigInteger k = ECUtil.generateK(n, random);
- ECPoint g = key.getParameters().getG();
- ECPoint gamma = g.multiply(k);
- ECPoint phi = key.getQ().multiply(k).add(cipherText.getY());
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+ BigInteger k = ECUtil.generateK(n, random);
+
+ ECPoint[] gamma_phi = new ECPoint[]{
+ basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()),
+ key.getQ().multiply(k).add(cipherText.getY())
+ };
+
+ ec.getCurve().normalizeAll(gamma_phi);
lastK = k;
- return new ECPair(cipherText.getX().add(gamma).normalize(), phi.normalize());
+ return new ECPair(gamma_phi[0], gamma_phi[1]);
}
/**
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
index d5f5fc85..38807a4c 100644
--- a/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ b/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
@@ -12,6 +12,7 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
public class ECKeyPairGenerator
implements AsymmetricCipherKeyPairGenerator, ECConstants
@@ -49,7 +50,7 @@ public class ECKeyPairGenerator
}
while (d.equals(ZERO) || (d.compareTo(n) >= 0));
- ECPoint Q = params.getG().multiply(d);
+ ECPoint Q = new FixedPointCombMultiplier().multiply(params.getG(), d);
return new AsymmetricCipherKeyPair(
new ECPublicKeyParameters(Q, params),
diff --git a/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java b/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
index dcdb752a..746d26ca 100755
--- a/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
+++ b/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
@@ -13,7 +13,9 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.KDFParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
@@ -121,8 +123,10 @@ public class ECIESKeyEncapsulation
// Compute the static-ephemeral key agreement
BigInteger rPrime = CofactorMode ? r.multiply(h).mod(n) : r;
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+
ECPoint[] ghTilde = new ECPoint[]{
- ecParams.getG().multiply(r),
+ basePointMultiplier.multiply(ecParams.getG(), r),
ecPubKey.getQ().multiply(rPrime)
};
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
index 8d326ffd..a5607d5a 100644
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
+++ b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
@@ -6,7 +6,9 @@ import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.prng.EntropySource;
import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
@@ -70,6 +72,7 @@ public class DualECSP800DRBG
private ECPoint _Q;
private byte[] _s;
private int _sLength;
+ private ECMultiplier _fixedPointMultiplier = new FixedPointCombMultiplier();
/**
* Construct a SP800-90A Dual EC DRBG.
@@ -199,7 +202,7 @@ public class DualECSP800DRBG
//System.err.println("S: " + new String(Hex.encode(_s)));
- byte[] r = _Q.multiply(s).normalize().getAffineXCoord().toBigInteger().toByteArray();
+ byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray();
if (r.length > _outlen)
{
@@ -220,7 +223,7 @@ public class DualECSP800DRBG
{
s = getScalarMultipleXCoord(_P, s);
- byte[] r = _Q.multiply(s).normalize().getAffineXCoord().toBigInteger().toByteArray();
+ byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray();
int required = output.length - outOffset;
@@ -237,7 +240,7 @@ public class DualECSP800DRBG
}
// Need to preserve length of S as unsigned int.
- _s = BigIntegers.asUnsignedByteArray(_sLength, _P.multiply(s).normalize().getAffineXCoord().toBigInteger());
+ _s = BigIntegers.asUnsignedByteArray(_sLength, getScalarMultipleXCoord(_P, s));
return numberOfBits;
}
@@ -302,6 +305,6 @@ public class DualECSP800DRBG
private BigInteger getScalarMultipleXCoord(ECPoint p, BigInteger s)
{
- return p.multiply(s).normalize().getAffineXCoord().toBigInteger();
+ return _fixedPointMultiplier.multiply(p, s).normalize().getAffineXCoord().toBigInteger();
}
}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java b/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
index bcc4edf2..0a3ef37f 100644
--- a/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
+++ b/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
@@ -13,7 +13,9 @@ import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.Arrays;
/**
@@ -57,9 +59,9 @@ public class DSTU4145Signer
public BigInteger[] generateSignature(byte[] message)
{
- ECDomainParameters parameters = key.getParameters();
+ ECDomainParameters ec = key.getParameters();
- ECCurve curve = parameters.getCurve();
+ ECCurve curve = ec.getCurve();
ECFieldElement h = hash2FieldElement(curve, message);
if (h.isZero())
@@ -67,10 +69,14 @@ public class DSTU4145Signer
h = curve.fromBigInteger(ONE);
}
- BigInteger n = parameters.getN();
+ BigInteger n = ec.getN();
BigInteger e, r, s;
ECFieldElement Fe, y;
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+
do
{
do
@@ -78,7 +84,7 @@ public class DSTU4145Signer
do
{
e = generateRandomInteger(n, random);
- Fe = parameters.getG().multiply(e).normalize().getAffineXCoord();
+ Fe = basePointMultiplier.multiply(ec.getG(), e).normalize().getAffineXCoord();
}
while (Fe.isZero());
@@ -87,7 +93,7 @@ public class DSTU4145Signer
}
while (r.signum() == 0);
- s = r.multiply(((ECPrivateKeyParameters)key).getD()).add(e).mod(n);
+ s = r.multiply(d).add(e).mod(n);
}
while (s.signum() == 0);
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java b/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
index f6d7f4fa..47dc6bd9 100644
--- a/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
+++ b/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
@@ -1,158 +1,155 @@
-package org.bouncycastle.crypto.signers;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECPoint;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * GOST R 34.10-2001 Signature Algorithm
- */
-public class ECGOST3410Signer
- implements DSA
-{
- ECKeyParameters key;
-
- SecureRandom random;
-
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- this.key = (ECPrivateKeyParameters)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- this.key = (ECPrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (ECPublicKeyParameters)param;
- }
- }
-
- /**
- * generate a signature for the given message using the key we were
- * initialised with. For conventional GOST3410 the message should be a GOST3411
- * hash of the message of interest.
- *
- * @param message the message that will be verified later.
- */
- public BigInteger[] generateSignature(
- byte[] message)
- {
- byte[] mRev = new byte[message.length]; // conversion is little-endian
- for (int i = 0; i != mRev.length; i++)
- {
- mRev[i] = message[mRev.length - 1 - i];
- }
-
- BigInteger e = new BigInteger(1, mRev);
- BigInteger n = key.getParameters().getN();
-
- BigInteger r = null;
- BigInteger s = null;
-
- do // generate s
- {
- BigInteger k = null;
-
- do // generate r
- {
- do
- {
- k = new BigInteger(n.bitLength(), random);
- }
- while (k.equals(ECConstants.ZERO));
-
- ECPoint p = key.getParameters().getG().multiply(k).normalize();
-
- BigInteger x = p.getAffineXCoord().toBigInteger();
-
- r = x.mod(n);
- }
- while (r.equals(ECConstants.ZERO));
-
- BigInteger d = ((ECPrivateKeyParameters)key).getD();
-
- s = (k.multiply(e)).add(d.multiply(r)).mod(n);
- }
- while (s.equals(ECConstants.ZERO));
-
- BigInteger[] res = new BigInteger[2];
-
- res[0] = r;
- res[1] = s;
-
- return res;
- }
-
- /**
- * return true if the value r and s represent a GOST3410 signature for
- * the passed in message (for standard GOST3410 the message should be
- * a GOST3411 hash of the real message to be verified).
- */
- public boolean verifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
- {
- byte[] mRev = new byte[message.length]; // conversion is little-endian
- for (int i = 0; i != mRev.length; i++)
- {
- mRev[i] = message[mRev.length - 1 - i];
- }
-
- BigInteger e = new BigInteger(1, mRev);
- BigInteger n = key.getParameters().getN();
-
- // r in the range [1,n-1]
- if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
- {
- return false;
- }
-
- // s in the range [1,n-1]
- if (s.compareTo(ECConstants.ONE) < 0 || s.compareTo(n) >= 0)
- {
- return false;
- }
-
- BigInteger v = e.modInverse(n);
-
- BigInteger z1 = s.multiply(v).mod(n);
- BigInteger z2 = (n.subtract(r)).multiply(v).mod(n);
-
- ECPoint G = key.getParameters().getG(); // P
- ECPoint Q = ((ECPublicKeyParameters)key).getQ();
-
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2).normalize();
-
- // components must be bogus.
- if (point.isInfinity())
- {
- return false;
- }
-
- BigInteger R = point.getAffineXCoord().toBigInteger().mod(n);
-
- return R.equals(r);
- }
-}
+package org.bouncycastle.crypto.signers;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECKeyParameters;
+import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.math.ec.ECAlgorithms;
+import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECMultiplier;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * GOST R 34.10-2001 Signature Algorithm
+ */
+public class ECGOST3410Signer
+ implements DSA
+{
+ ECKeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional GOST3410 the message should be a GOST3411
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger e = new BigInteger(1, mRev);
+
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ BigInteger r, s;
+
+ ECMultiplier basePointMultiplier = new FixedPointCombMultiplier();
+
+ do // generate s
+ {
+ BigInteger k;
+ do // generate r
+ {
+ do
+ {
+ k = new BigInteger(n.bitLength(), random);
+ }
+ while (k.equals(ECConstants.ZERO));
+
+ ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize();
+
+ r = p.getAffineXCoord().toBigInteger().mod(n);
+ }
+ while (r.equals(ECConstants.ZERO));
+
+ s = (k.multiply(e)).add(d.multiply(r)).mod(n);
+ }
+ while (s.equals(ECConstants.ZERO));
+
+ return new BigInteger[]{ r, s };
+ }
+
+ /**
+ * return true if the value r and s represent a GOST3410 signature for
+ * the passed in message (for standard GOST3410 the message should be
+ * a GOST3411 hash of the real message to be verified).
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger e = new BigInteger(1, mRev);
+ BigInteger n = key.getParameters().getN();
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.compareTo(ECConstants.ONE) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger v = e.modInverse(n);
+
+ BigInteger z1 = s.multiply(v).mod(n);
+ BigInteger z2 = (n.subtract(r)).multiply(v).mod(n);
+
+ ECPoint G = key.getParameters().getG(); // P
+ ECPoint Q = ((ECPublicKeyParameters)key).getQ();
+
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2).normalize();
+
+ // components must be bogus.
+ if (point.isInfinity())
+ {
+ return false;
+ }
+
+ BigInteger R = point.getAffineXCoord().toBigInteger().mod(n);
+
+ return R.equals(r);
+ }
+}