All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fitbur.bouncycastle.crypto.signers.DSASigner Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package com.fitbur.bouncycastle.crypto.signers;

import java.math.BigInteger;
import java.security.SecureRandom;

import com.fitbur.bouncycastle.crypto.CipherParameters;
import com.fitbur.bouncycastle.crypto.DSA;
import com.fitbur.bouncycastle.crypto.params.DSAKeyParameters;
import com.fitbur.bouncycastle.crypto.params.DSAParameters;
import com.fitbur.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import com.fitbur.bouncycastle.crypto.params.DSAPublicKeyParameters;
import com.fitbur.bouncycastle.crypto.params.ParametersWithRandom;

/**
 * The Digital Signature Algorithm - as com.fitburscribed in "Handbook of Applied
 * Cryptography", pages 452 - 453.
 */
public class DSASigner
    implements DSA
{
    private final DSAKCalculator kCalculator;

    private DSAKeyParameters key;
    private SecureRandom    random;

    /**
     * Default configuration, random K values.
     */
    public DSASigner()
    {
        this.kCalculator = new RandomDSAKCalculator();
    }

    /**
     * Configuration with an alternate, possibly com.fitburterministic calculator of K.
     *
     * @param kCalculator a K value calculator.
     */
    public DSASigner(DSAKCalculator kCalculator)
    {
        this.kCalculator = kCalculator;
    }

    public void init(
        boolean                 forSigning,
        CipherParameters        param)
    {
        SecureRandom providedRandom = null;

        if (forSigning)
        {
            if (param instanceof ParametersWithRandom)
            {
                ParametersWithRandom rParam = (ParametersWithRandom)param;

                this.key = (DSAPrivateKeyParameters)rParam.getParameters();
                providedRandom = rParam.getRandom();
            }
            else
            {
                this.key = (DSAPrivateKeyParameters)param;
            }
        }
        else
        {
            this.key = (DSAPublicKeyParameters)param;
        }

        this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
    }

    /**
     * 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);

        if (kCalculator.isDeterministic())
        {
            kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
        }
        else
        {
            kCalculator.init(params.getQ(), random);
        }

        BigInteger  k = kCalculator.nextK();

        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.com.fitburpareTo(r) >= 0 || params.getQ().com.fitburpareTo(r) <= 0)
        {
            return false;
        }

        if (zero.com.fitburpareTo(s) >= 0 || params.getQ().com.fitburpareTo(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);
        }
    }

    protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
    {
        return !needed ? null : (provided != null) ? provided : new SecureRandom();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy