001: package org.bouncycastle.crypto.signers;
002:
003: import org.bouncycastle.crypto.CipherParameters;
004: import org.bouncycastle.crypto.DSA;
005: import org.bouncycastle.crypto.params.ECKeyParameters;
006: import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
007: import org.bouncycastle.crypto.params.ECPublicKeyParameters;
008: import org.bouncycastle.crypto.params.ParametersWithRandom;
009: import org.bouncycastle.math.ec.ECAlgorithms;
010: import org.bouncycastle.math.ec.ECConstants;
011: import org.bouncycastle.math.ec.ECPoint;
012:
013: import java.math.BigInteger;
014: import java.security.SecureRandom;
015:
016: /**
017: * EC-DSA as described in X9.62
018: */
019: public class ECDSASigner implements ECConstants, DSA {
020: ECKeyParameters key;
021:
022: SecureRandom random;
023:
024: public void init(boolean forSigning, CipherParameters param) {
025: if (forSigning) {
026: if (param instanceof ParametersWithRandom) {
027: ParametersWithRandom rParam = (ParametersWithRandom) param;
028:
029: this .random = rParam.getRandom();
030: this .key = (ECPrivateKeyParameters) rParam
031: .getParameters();
032: } else {
033: this .random = new SecureRandom();
034: this .key = (ECPrivateKeyParameters) param;
035: }
036: } else {
037: this .key = (ECPublicKeyParameters) param;
038: }
039: }
040:
041: // 5.3 pg 28
042: /**
043: * generate a signature for the given message using the key we were
044: * initialised with. For conventional DSA the message should be a SHA-1
045: * hash of the message of interest.
046: *
047: * @param message the message that will be verified later.
048: */
049: public BigInteger[] generateSignature(byte[] message) {
050: BigInteger n = key.getParameters().getN();
051: BigInteger e = calculateE(n, message);
052: BigInteger r = null;
053: BigInteger s = null;
054:
055: // 5.3.2
056: do // generate s
057: {
058: BigInteger k = null;
059: int nBitLength = n.bitLength();
060:
061: do // generate r
062: {
063: do {
064: k = new BigInteger(nBitLength, random);
065: } while (k.equals(ZERO));
066:
067: ECPoint p = key.getParameters().getG().multiply(k);
068:
069: // 5.3.3
070: BigInteger x = p.getX().toBigInteger();
071:
072: r = x.mod(n);
073: } while (r.equals(ZERO));
074:
075: BigInteger d = ((ECPrivateKeyParameters) key).getD();
076:
077: s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
078: } while (s.equals(ZERO));
079:
080: BigInteger[] res = new BigInteger[2];
081:
082: res[0] = r;
083: res[1] = s;
084:
085: return res;
086: }
087:
088: // 5.4 pg 29
089: /**
090: * return true if the value r and s represent a DSA signature for
091: * the passed in message (for standard DSA the message should be
092: * a SHA-1 hash of the real message to be verified).
093: */
094: public boolean verifySignature(byte[] message, BigInteger r,
095: BigInteger s) {
096: BigInteger n = key.getParameters().getN();
097: BigInteger e = calculateE(n, message);
098:
099: // r in the range [1,n-1]
100: if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0) {
101: return false;
102: }
103:
104: // s in the range [1,n-1]
105: if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0) {
106: return false;
107: }
108:
109: BigInteger c = s.modInverse(n);
110:
111: BigInteger u1 = e.multiply(c).mod(n);
112: BigInteger u2 = r.multiply(c).mod(n);
113:
114: ECPoint G = key.getParameters().getG();
115: ECPoint Q = ((ECPublicKeyParameters) key).getQ();
116:
117: ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2);
118:
119: BigInteger v = point.getX().toBigInteger().mod(n);
120:
121: return v.equals(r);
122: }
123:
124: private BigInteger calculateE(BigInteger n, byte[] message) {
125: if (n.bitLength() > message.length * 8) {
126: return new BigInteger(1, message);
127: } else {
128: byte[] trunc = new byte[n.bitLength() / 8];
129:
130: System.arraycopy(message, 0, trunc, 0, trunc.length);
131:
132: return new BigInteger(1, trunc);
133: }
134: }
135: }
|