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/DSASigner.java')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java138
1 files changed, 138 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
new file mode 100644
index 00000000..a96cef07
--- /dev/null
+++ b/core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -0,0 +1,138 @@
+package org.bouncycastle.crypto.signers;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.params.DSAKeyParameters;
+import org.bouncycastle.crypto.params.DSAParameters;
+import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * The Digital Signature Algorithm - as described in "Handbook of Applied
+ * Cryptography", pages 452 - 453.
+ */
+public class DSASigner
+ implements DSA
+{
+ DSAKeyParameters 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 = (DSAPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (DSAPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (DSAPublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * 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)
+ {
+ DSAParameters params = key.getParameters();
+ BigInteger m = calculateE(params.getQ(), message);
+ BigInteger k;
+ int qBitLength = params.getQ().bitLength();
+
+ do
+ {
+ k = new BigInteger(qBitLength, random);
+ }
+ while (k.compareTo(params.getQ()) >= 0);
+
+ BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
+
+ k = k.modInverse(params.getQ()).multiply(
+ m.add(((DSAPrivateKeyParameters)key).getX().multiply(r)));
+
+ BigInteger s = k.mod(params.getQ());
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ /**
+ * 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)
+ {
+ DSAParameters params = key.getParameters();
+ BigInteger m = calculateE(params.getQ(), message);
+ BigInteger zero = BigInteger.valueOf(0);
+
+ if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+ {
+ return false;
+ }
+
+ if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+ {
+ return false;
+ }
+
+ BigInteger w = s.modInverse(params.getQ());
+
+ BigInteger u1 = m.multiply(w).mod(params.getQ());
+ BigInteger u2 = r.multiply(w).mod(params.getQ());
+
+ u1 = params.getG().modPow(u1, params.getP());
+ u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, params.getP());
+
+ BigInteger v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());
+
+ return v.equals(r);
+ }
+
+ private BigInteger calculateE(BigInteger n, byte[] message)
+ {
+ if (n.bitLength() >= message.length * 8)
+ {
+ return new BigInteger(1, message);
+ }
+ else
+ {
+ byte[] trunc = new byte[n.bitLength() / 8];
+
+ System.arraycopy(message, 0, trunc, 0, trunc.length);
+
+ return new BigInteger(1, trunc);
+ }
+ }
+}