package org.bouncycastle.crypto.signers;

import java.math.BigInteger;

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.DSAExt;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ParametersWithRandom;

public class DSADigestSigner
    implements Signer
{
    private final DSA dsa;
    private final Digest digest;
    private final DSAEncoding encoding;
    private boolean forSigning;

    public DSADigestSigner(
        DSA     dsa,
        Digest  digest)
    {
        this.dsa = dsa;
        this.digest = digest;
        this.encoding = StandardDSAEncoding.INSTANCE;
    }

    public DSADigestSigner(
        DSAExt      dsa,
        Digest      digest,
        DSAEncoding encoding)
    {
        this.dsa = dsa;
        this.digest = digest;
        this.encoding = encoding;
    }

    public void init(
        boolean           forSigning,
        CipherParameters   parameters)
    {
        this.forSigning = forSigning;

        AsymmetricKeyParameter k;

        if (parameters instanceof ParametersWithRandom)
        {
            k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
        }
        else
        {
            k = (AsymmetricKeyParameter)parameters;
        }

        if (forSigning && !k.isPrivate())
        {
            throw new IllegalArgumentException("Signing Requires Private Key.");
        }

        if (!forSigning && k.isPrivate())
        {
            throw new IllegalArgumentException("Verification Requires Public Key.");
        }

        reset();

        dsa.init(forSigning, parameters);
    }

    
update the internal digest with the byte b
/** * update the internal digest with the byte b */
public void update( byte input) { digest.update(input); }
update the internal digest with the byte array in
/** * update the internal digest with the byte array in */
public void update( byte[] input, int inOff, int length) { digest.update(input, inOff, length); }
Generate a signature for the message we've been loaded with using the key we were initialised with.
/** * Generate a signature for the message we've been loaded with using * the key we were initialised with. */
public byte[] generateSignature() { if (!forSigning) { throw new IllegalStateException("DSADigestSigner not initialised for signature generation."); } byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); BigInteger[] sig = dsa.generateSignature(hash); try { return encoding.encode(getOrder(), sig[0], sig[1]); } catch (Exception e) { throw new IllegalStateException("unable to encode signature"); } } public boolean verifySignature( byte[] signature) { if (forSigning) { throw new IllegalStateException("DSADigestSigner not initialised for verification"); } byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); try { BigInteger[] sig = encoding.decode(getOrder(), signature); return dsa.verifySignature(hash, sig[0], sig[1]); } catch (Exception e) { return false; } } public void reset() { digest.reset(); } protected BigInteger getOrder() { return dsa instanceof DSAExt ? ((DSAExt)dsa).getOrder() : null; } }