RSADigestSigner.java revision 5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)package org.bouncycastle.crypto.signers;
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.IOException;
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.Hashtable;
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.ASN1Encoding;
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.ASN1ObjectIdentifier;
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.DERNull;
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.x509.DigestInfo;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.crypto.AsymmetricBlockCipher;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.crypto.CipherParameters;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.crypto.CryptoException;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.crypto.DataLengthException;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.crypto.Digest;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.bouncycastle.crypto.Signer;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.bouncycastle.crypto.encodings.PKCS1Encoding;
22bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochimport org.bouncycastle.crypto.engines.RSABlindedEngine;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import org.bouncycastle.crypto.params.ParametersWithRandom;
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import org.bouncycastle.util.Arrays;
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class RSADigestSigner
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    implements Signer
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private final AlgorithmIdentifier algId;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private final Digest digest;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private boolean forSigning;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final Hashtable oidMap = new Hashtable();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Load OID table.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    static
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // BEGIN android-removed
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // END android-removed
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // BEGIN android-removed
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // oidMap.put("MD2", PKCSObjectIdentifiers.md2);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // oidMap.put("MD4", PKCSObjectIdentifiers.md4);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // END android-removed
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oidMap.put("MD5", PKCSObjectIdentifiers.md5);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public RSADigestSigner(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Digest digest)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public RSADigestSigner(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Digest digest,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASN1ObjectIdentifier digestOid)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.digest = digest;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @deprecated
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public String getAlgorithmName()
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return digest.getAlgorithmName() + "withRSA";
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * initialise the signer for signing or verification.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param forSigning
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *            true if for signing, false otherwise
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param parameters
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)     *            necessary parameters.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
9158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    public void init(
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        boolean          forSigning,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CipherParameters parameters)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.forSigning = forSigning;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AsymmetricKeyParameter k;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (parameters instanceof ParametersWithRandom)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            k = (AsymmetricKeyParameter)parameters;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (forSigning && !k.isPrivate())
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            throw new IllegalArgumentException("signing requires private key");
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!forSigning && k.isPrivate())
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            throw new IllegalArgumentException("verification requires public key");
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reset();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rsaEngine.init(forSigning, parameters);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * update the internal digest with the byte b
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    public void update(
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        byte input)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digest.update(input);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * update the internal digest with the byte array in
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void update(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte[]  input,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int     inOff,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int     length)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digest.update(input, inOff, length);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Generate a signature for the message we've been loaded with using the key
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we were initialised with.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public byte[] generateSignature()
147558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        throws CryptoException, DataLengthException
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!forSigning)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte[] hash = new byte[digest.getDigestSize()];
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digest.doFinal(hash, 0);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            byte[] data = derEncode(hash);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return rsaEngine.processBlock(data, 0, data.length);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        catch (IOException e)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * return true if the internal state represents the signature described in
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the passed in array.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public boolean verifySignature(
173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        byte[] signature)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (forSigning)
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            throw new IllegalStateException("RSADigestSigner not initialised for verification");
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte[] hash = new byte[digest.getDigestSize()];
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digest.doFinal(hash, 0);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte[] sig;
185a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        byte[] expected;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            sig = rsaEngine.processBlock(signature, 0, signature.length);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            expected = derEncode(hash);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        catch (Exception e)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (sig.length == expected.length)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return Arrays.constantTimeAreEqual(sig, expected);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        else if (sig.length == expected.length - 2)  // NULL left out
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int sigOffset = sig.length - hash.length - 2;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int expectedOffset = expected.length - hash.length - 2;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            expected[1] -= 2;      // adjust lengths
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            expected[3] -= 2;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int nonEqual = 0;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (int i = 0; i < hash.length; i++)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (int i = 0; i < sigOffset; i++)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                nonEqual |= (sig[i] ^ expected[i]);  // check header less NULL
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            return nonEqual == 0;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void reset()
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digest.reset();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private byte[] derEncode(
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        byte[] hash)
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        throws IOException
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    {
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        DigestInfo dInfo = new DigestInfo(algId, hash);
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return dInfo.getEncoded(ASN1Encoding.DER);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)