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/crypto/signers/ECDSASigner.java')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java169
1 files changed, 169 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
new file mode 100644
index 00000000..a80c574b
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
@@ -0,0 +1,169 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+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;
+
+/**
+ * EC-DSA as described in X9.62
+ */
+public class ECDSASigner
+ implements ECConstants, 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;
+ }
+ }
+
+ // 5.3 pg 28
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional DSA the message should be a SHA-1
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ BigInteger n = key.getParameters().getN();
+ BigInteger e = calculateE(n, message);
+ BigInteger r = null;
+ BigInteger s = null;
+
+ // 5.3.2
+ do // generate s
+ {
+ BigInteger k = null;
+ int nBitLength = n.bitLength();
+
+ do // generate r
+ {
+ do
+ {
+ k = new BigInteger(nBitLength, random);
+ }
+ while (k.equals(ZERO) || k.compareTo(n) >= 0);
+
+ ECPoint p = key.getParameters().getG().multiply(k);
+
+ // 5.3.3
+ BigInteger x = p.getX().toBigInteger();
+
+ r = x.mod(n);
+ }
+ while (r.equals(ZERO));
+
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+ }
+ while (s.equals(ZERO));
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ // 5.4 pg 29
+ /**
+ * return true if the value r and s represent a DSA signature for
+ * the passed in message (for standard DSA the message should be
+ * a SHA-1 hash of the real message to be verified).
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ BigInteger n = key.getParameters().getN();
+ BigInteger e = calculateE(n, message);
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger c = s.modInverse(n);
+
+ BigInteger u1 = e.multiply(c).mod(n);
+ BigInteger u2 = r.multiply(c).mod(n);
+
+ ECPoint G = key.getParameters().getG();
+ ECPoint Q = ((ECPublicKeyParameters)key).getQ();
+
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2);
+
+ // components must be bogus.
+ if (point.isInfinity())
+ {
+ return false;
+ }
+
+ BigInteger v = point.getX().toBigInteger().mod(n);
+
+ return v.equals(r);
+ }
+
+ private BigInteger calculateE(BigInteger n, byte[] message)
+ {
+ int log2n = n.bitLength();
+ int messageBitLength = message.length * 8;
+
+ if (log2n >= messageBitLength)
+ {
+ return new BigInteger(1, message);
+ }
+ else
+ {
+ BigInteger trunc = new BigInteger(1, message);
+
+ trunc = trunc.shiftRight(messageBitLength - log2n);
+
+ return trunc;
+ }
+ }
+}