FileDocCategorySizeDatePackage
ElGamalSignature.javaAPI DocExample3577Wed Apr 01 18:14:08 BST 1998oreilly.jonathan.crypto

ElGamalSignature.java

package oreilly.jonathan.crypto;

import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.*;

public class ElGamalSignature
    extends SignatureSpi {

  protected ElGamalKey mKey;

  protected ByteArrayOutputStream mOut;

  protected static BigInteger kOne = BigInteger.valueOf(1);
  
  protected void engineInitVerify(PublicKey key)
      throws InvalidKeyException {
    if (!(key instanceof ElGamalPublicKey))
      throw new InvalidKeyException("I didn't get an ElGamalPublicKey.");
    mKey = (ElGamalKey)key;
    mOut = new ByteArrayOutputStream();
  }

  protected void engineInitSign(PrivateKey key) throws InvalidKeyException {
    if (!(key instanceof ElGamalPrivateKey))
      throw new InvalidKeyException("I didn't get an ElGamalPrivateKey.");
    mKey = (ElGamalKey)key;
    mOut = new ByteArrayOutputStream();
  }

  protected void engineUpdate(byte b) throws SignatureException {
    mOut.write(b);
  }
  
  protected void engineUpdate(byte[] b, int off, int len)
      throws SignatureException {
    mOut.write(b, off, len);
  }

  protected byte[] engineSign() throws SignatureException {
    BigInteger x = ((ElGamalPrivateKey)mKey).getX();
    BigInteger g = mKey.getG();
    BigInteger p = mKey.getP();
    BigInteger pminusone = p.subtract(kOne);

    BigInteger k;
    do {
      k = new BigInteger(p.bitLength() - 1, new SecureRandom());
    } while (k.gcd(pminusone).equals(kOne) == false);

    BigInteger m = new BigInteger(1, mOut.toByteArray());

    BigInteger a = g.modPow(k, p);
    BigInteger top = m.subtract(x.multiply(a)).mod(pminusone);
    BigInteger b = top.multiply(
        k.modPow(kOne.negate(), pminusone)).mod(pminusone);

    int modulusLength = (p.bitLength() + 7) / 8;
    byte[] signature = new byte[modulusLength * 2];
    byte[] aBytes = getBytes(a);
    int aLength = aBytes.length;
    byte[] bBytes = getBytes(b);
    int bLength = bBytes.length;
    System.arraycopy(aBytes, 0,
        signature, modulusLength - aLength, aLength);
    System.arraycopy(bBytes, 0,
        signature, modulusLength * 2 - bLength, bLength);
    return signature;
  }

  protected boolean engineVerify(byte[] sigBytes)
      throws SignatureException {
    BigInteger y = ((ElGamalPublicKey)mKey).getY();
    BigInteger g = mKey.getG();
    BigInteger p = mKey.getP();

    int modulusLength = (p.bitLength() + 7) / 8;
    byte[] aBytes = new byte[modulusLength];
    byte[] bBytes = new byte[modulusLength];
    System.arraycopy(sigBytes, 0, aBytes, 0, modulusLength);
    System.arraycopy(sigBytes, modulusLength, bBytes, 0, modulusLength);
    BigInteger a = new BigInteger(1, aBytes);
    BigInteger b = new BigInteger(1, bBytes);

    BigInteger first = y.modPow(a, p).multiply(a.modPow(b, p)).mod(p);

    BigInteger m = new BigInteger(1, mOut.toByteArray());
    BigInteger second = g.modPow(m,p);
    
    return first.equals(second);
  }

  protected byte[] getBytes(BigInteger big) {
    byte[] bigBytes = big.toByteArray();
    if ((big.bitLength() % 8) != 0) {
      return bigBytes;
    }
    else {
      byte[] smallerBytes = new byte[big.bitLength() / 8];
      System.arraycopy(bigBytes, 1, smallerBytes, 0, smallerBytes.length);
      return smallerBytes;
    }
  }

  protected void engineSetParameter(String param, Object value)
      throws InvalidParameterException {}
  protected Object engineGetParameter(String param)
      throws InvalidParameterException { return null; }
}