package org.bouncycastle.crypto.signers;

import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.util.Arrays;

public class GenericSigner
    implements Signer
{
    private final AsymmetricBlockCipher engine;
    private final Digest digest;
    private boolean forSigning;

    public GenericSigner(
        AsymmetricBlockCipher engine,
        Digest                digest)
    {
        this.engine = engine;
        this.digest = digest;
    }

    
initialise the signer for signing or verification.
Params:
  • forSigning – true if for signing, false otherwise
  • parameters – necessary parameters.
/** * initialise the signer for signing or verification. * * @param forSigning * true if for signing, false otherwise * @param parameters * necessary parameters. */
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(); engine.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() throws CryptoException, DataLengthException { if (!forSigning) { throw new IllegalStateException("GenericSigner not initialised for signature generation."); } byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); return engine.processBlock(hash, 0, hash.length); }
return true if the internal state represents the signature described in the passed in array.
/** * return true if the internal state represents the signature described in * the passed in array. */
public boolean verifySignature( byte[] signature) { if (forSigning) { throw new IllegalStateException("GenericSigner not initialised for verification"); } byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); try { byte[] sig = engine.processBlock(signature, 0, signature.length); // Extend with leading zeroes to match the digest size, if necessary. if (sig.length < hash.length) { byte[] tmp = new byte[hash.length]; System.arraycopy(sig, 0, tmp, tmp.length - sig.length, sig.length); sig = tmp; } return Arrays.constantTimeAreEqual(sig, hash); } catch (Exception e) { return false; } } public void reset() { digest.reset(); } }