org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder.java

Source

package org.bouncycastle.operator.jcajce;

import java.io.IOException;
import java.io.OutputStream;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import org.bouncycastle.operator.ContentVerifier;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.OperatorStreamException;
import org.bouncycastle.operator.RawContentVerifier;
import org.bouncycastle.operator.RuntimeOperatorException;

public class JcaContentVerifierProviderBuilder {
    private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper());

    public JcaContentVerifierProviderBuilder() {
    }

    public JcaContentVerifierProviderBuilder setProvider(Provider provider) {
        this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider));

        return this;
    }

    public JcaContentVerifierProviderBuilder setProvider(String providerName) {
        this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName));

        return this;
    }

    public ContentVerifierProvider build(X509CertificateHolder certHolder)
            throws OperatorCreationException, CertificateException {
        return build(helper.convertCertificate(certHolder));
    }

    public ContentVerifierProvider build(final X509Certificate certificate) throws OperatorCreationException {
        final X509CertificateHolder certHolder;

        try {
            certHolder = new JcaX509CertificateHolder(certificate);
        } catch (CertificateEncodingException e) {
            throw new OperatorCreationException("cannot process certificate: " + e.getMessage(), e);
        }

        return new ContentVerifierProvider() {
            private SignatureOutputStream stream;

            public boolean hasAssociatedCertificate() {
                return true;
            }

            public X509CertificateHolder getAssociatedCertificate() {
                return certHolder;
            }

            public ContentVerifier get(AlgorithmIdentifier algorithm) throws OperatorCreationException {
                try {
                    Signature sig = helper.createSignature(algorithm);

                    sig.initVerify(certificate.getPublicKey());

                    stream = new SignatureOutputStream(sig);
                } catch (Exception e) {
                    throw new OperatorCreationException("exception on setup: " + e, e);
                }

                Signature rawSig = createRawSig(algorithm, certificate.getPublicKey());

                if (rawSig != null) {
                    return new RawSigVerifier(algorithm, stream, rawSig);
                } else {
                    return new SigVerifier(algorithm, stream);
                }
            }
        };
    }

    public ContentVerifierProvider build(final PublicKey publicKey) throws OperatorCreationException {
        return new ContentVerifierProvider() {
            public boolean hasAssociatedCertificate() {
                return false;
            }

            public X509CertificateHolder getAssociatedCertificate() {
                return null;
            }

            public ContentVerifier get(AlgorithmIdentifier algorithm) throws OperatorCreationException {
                SignatureOutputStream stream = createSignatureStream(algorithm, publicKey);

                Signature rawSig = createRawSig(algorithm, publicKey);

                if (rawSig != null) {
                    return new RawSigVerifier(algorithm, stream, rawSig);
                } else {
                    return new SigVerifier(algorithm, stream);
                }
            }
        };
    }

    public ContentVerifierProvider build(SubjectPublicKeyInfo publicKey) throws OperatorCreationException {
        return this.build(helper.convertPublicKey(publicKey));
    }

    private SignatureOutputStream createSignatureStream(AlgorithmIdentifier algorithm, PublicKey publicKey)
            throws OperatorCreationException {
        try {
            Signature sig = helper.createSignature(algorithm);

            sig.initVerify(publicKey);

            return new SignatureOutputStream(sig);
        } catch (Exception e) {
            throw new OperatorCreationException("exception on setup: " + e, e);
        }
    }

    private Signature createRawSig(AlgorithmIdentifier algorithm, PublicKey publicKey) {
        Signature rawSig;
        try {
            rawSig = helper.createRawSignature(algorithm);

            if (rawSig != null) {
                rawSig.initVerify(publicKey);
            }
        } catch (Exception e) {
            rawSig = null;
        }
        return rawSig;
    }

    private class SigVerifier implements ContentVerifier {
        private SignatureOutputStream stream;
        private AlgorithmIdentifier algorithm;

        SigVerifier(AlgorithmIdentifier algorithm, SignatureOutputStream stream) {
            this.algorithm = algorithm;
            this.stream = stream;
        }

        public AlgorithmIdentifier getAlgorithmIdentifier() {
            return algorithm;
        }

        public OutputStream getOutputStream() {
            if (stream == null) {
                throw new IllegalStateException("verifier not initialised");
            }

            return stream;
        }

        public boolean verify(byte[] expected) {
            try {
                return stream.verify(expected);
            } catch (SignatureException e) {
                throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e);
            }
        }
    }

    private class RawSigVerifier extends SigVerifier implements RawContentVerifier {
        private Signature rawSignature;

        RawSigVerifier(AlgorithmIdentifier algorithm, SignatureOutputStream stream, Signature rawSignature) {
            super(algorithm, stream);
            this.rawSignature = rawSignature;
        }

        public boolean verify(byte[] digest, byte[] expected) {
            try {
                rawSignature.update(digest);

                return rawSignature.verify(expected);
            } catch (SignatureException e) {
                throw new RuntimeOperatorException("exception obtaining raw signature: " + e.getMessage(), e);
            }
        }
    }

    private class SignatureOutputStream extends OutputStream {
        private Signature sig;

        SignatureOutputStream(Signature sig) {
            this.sig = sig;
        }

        public void write(byte[] bytes, int off, int len) throws IOException {
            try {
                sig.update(bytes, off, len);
            } catch (SignatureException e) {
                throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e);
            }
        }

        public void write(byte[] bytes) throws IOException {
            try {
                sig.update(bytes);
            } catch (SignatureException e) {
                throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e);
            }
        }

        public void write(int b) throws IOException {
            try {
                sig.update((byte) b);
            } catch (SignatureException e) {
                throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e);
            }
        }

        boolean verify(byte[] expected) throws SignatureException {
            return sig.verify(expected);
        }
    }
}