org.votingsystem.signature.util.CMSUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.votingsystem.signature.util.CMSUtils.java

Source

package org.votingsystem.signature.util;

import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.cms.*;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.CertificateList;
import org.bouncycastle.asn1.x509.TBSCertificateStructure;
import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.tsp.TimeStampToken;
import org.bouncycastle.util.io.Streams;

import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.*;
import java.security.cert.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
* License: https://github.com/votingsystem/votingsystem/wiki/Licencia
*/
public class CMSUtils {

    public static final String DIGEST_SHA1 = OIWObjectIdentifiers.idSHA1.getId();
    public static final String DIGEST_SHA224 = NISTObjectIdentifiers.id_sha224.getId();
    public static final String DIGEST_SHA256 = NISTObjectIdentifiers.id_sha256.getId();
    public static final String DIGEST_SHA384 = NISTObjectIdentifiers.id_sha384.getId();
    public static final String DIGEST_SHA512 = NISTObjectIdentifiers.id_sha512.getId();
    public static final String DIGEST_MD5 = PKCSObjectIdentifiers.md5.getId();
    public static final String DIGEST_GOST3411 = CryptoProObjectIdentifiers.gostR3411.getId();
    public static final String DIGEST_RIPEMD128 = TeleTrusTObjectIdentifiers.ripemd128.getId();
    public static final String DIGEST_RIPEMD160 = TeleTrusTObjectIdentifiers.ripemd160.getId();
    public static final String DIGEST_RIPEMD256 = TeleTrusTObjectIdentifiers.ripemd256.getId();

    public static final String ENCRYPTION_RSA = PKCSObjectIdentifiers.rsaEncryption.getId();
    public static final String ENCRYPTION_DSA = X9ObjectIdentifiers.id_dsa_with_sha1.getId();
    public static final String ENCRYPTION_ECDSA = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
    public static final String ENCRYPTION_RSA_PSS = PKCSObjectIdentifiers.id_RSASSA_PSS.getId();
    public static final String ENCRYPTION_GOST3410 = CryptoProObjectIdentifiers.gostR3410_94.getId();
    public static final String ENCRYPTION_ECGOST3410 = CryptoProObjectIdentifiers.gostR3410_2001.getId();

    private static final String ENCRYPTION_ECDSA_WITH_SHA1 = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
    private static final String ENCRYPTION_ECDSA_WITH_SHA224 = X9ObjectIdentifiers.ecdsa_with_SHA224.getId();
    private static final String ENCRYPTION_ECDSA_WITH_SHA256 = X9ObjectIdentifiers.ecdsa_with_SHA256.getId();
    private static final String ENCRYPTION_ECDSA_WITH_SHA384 = X9ObjectIdentifiers.ecdsa_with_SHA384.getId();
    private static final String ENCRYPTION_ECDSA_WITH_SHA512 = X9ObjectIdentifiers.ecdsa_with_SHA512.getId();

    private static final Runtime RUNTIME = Runtime.getRuntime();

    static int getMaximumMemory() {
        long maxMem = RUNTIME.maxMemory();
        if (maxMem > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        return (int) maxMem;
    }

    static ContentInfo readContentInfo(byte[] input) throws CMSException {
        // enforce limit checking as from a byte array
        return readContentInfo(new ASN1InputStream(input));
    }

    static ContentInfo readContentInfo(InputStream input) throws CMSException {
        // enforce some limit checking
        return readContentInfo(new ASN1InputStream(input, getMaximumMemory()));
    }

    static List getCertificatesFromStore(CertStore certStore) throws CertStoreException, CMSException {
        List certs = new ArrayList();
        try {
            for (Iterator it = certStore.getCertificates(null).iterator(); it.hasNext();) {
                X509Certificate c = (X509Certificate) it.next();
                certs.add(X509CertificateStructure.getInstance(ASN1Object.fromByteArray(c.getEncoded())));
            }
            return certs;
        } catch (IllegalArgumentException e) {
            throw new CMSException("error processing certs", e);
        } catch (IOException e) {
            throw new CMSException("error processing certs", e);
        } catch (CertificateEncodingException e) {
            throw new CMSException("error encoding certs", e);
        }
    }

    static List getCRLsFromStore(CertStore certStore) throws CertStoreException, CMSException {
        List crls = new ArrayList();
        try {
            for (Iterator it = certStore.getCRLs(null).iterator(); it.hasNext();) {
                X509CRL c = (X509CRL) it.next();
                crls.add(CertificateList.getInstance(ASN1Object.fromByteArray(c.getEncoded())));
            }
            return crls;
        } catch (IllegalArgumentException e) {
            throw new CMSException("error processing crls", e);
        } catch (IOException e) {
            throw new CMSException("error processing crls", e);
        } catch (CRLException e) {
            throw new CMSException("error encoding crls", e);
        }
    }

    public static ASN1Set createBerSetFromList(List derObjects) {
        ASN1EncodableVector v = new ASN1EncodableVector();
        for (Iterator it = derObjects.iterator(); it.hasNext();) {
            v.add((DEREncodable) it.next());
        }
        return new BERSet(v);
    }

    static ASN1Set createDerSetFromList(List derObjects) {
        ASN1EncodableVector v = new ASN1EncodableVector();
        for (Iterator it = derObjects.iterator(); it.hasNext();) {
            v.add((DEREncodable) it.next());
        }
        return new DERSet(v);
    }

    static OutputStream createBEROctetOutputStream(OutputStream s, int tagNo, boolean isExplicit, int bufferSize)
            throws IOException {
        BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit);
        if (bufferSize != 0) {
            return octGen.getOctetOutputStream(new byte[bufferSize]);
        }
        return octGen.getOctetOutputStream();
    }

    static TBSCertificateStructure getTBSCertificateStructure(X509Certificate cert)
            throws CertificateEncodingException {
        try {
            return TBSCertificateStructure.getInstance(ASN1Object.fromByteArray(cert.getTBSCertificate()));
        } catch (IOException e) {
            throw new CertificateEncodingException(e.toString());
        }
    }

    private static ContentInfo readContentInfo(ASN1InputStream in) throws CMSException {
        try {
            return ContentInfo.getInstance(in.readObject());
        } catch (IOException e) {
            throw new CMSException("IOException reading content.", e);
        } catch (ClassCastException e) {
            throw new CMSException("Malformed content.", e);
        } catch (IllegalArgumentException e) {
            throw new CMSException("Malformed content.", e);
        }
    }

    public static byte[] streamToByteArray(InputStream in) throws IOException {
        return Streams.readAll(in);
    }

    public static byte[] streamToByteArray(InputStream in, int limit) throws IOException {
        return Streams.readAllLimited(in, limit);
    }

    public static Provider getProvider(String providerName) throws NoSuchProviderException {
        if (providerName != null) {
            Provider prov = Security.getProvider(providerName);
            if (prov != null) {
                return prov;
            }
            throw new NoSuchProviderException("provider " + providerName + " not found.");
        }
        return null;
    }

    public static SignerIdentifier getSignerIdentifier(X509Certificate cert) {
        TBSCertificateStructure tbs;
        try {
            tbs = CMSUtils.getTBSCertificateStructure(cert);
        } catch (CertificateEncodingException e) {
            throw new IllegalArgumentException("can't extract TBS structure from this cert");
        }
        //Aqui podra ser ...pkcs.IssuerAndSerialNumber
        IssuerAndSerialNumber encSid = new IssuerAndSerialNumber(tbs.getIssuer(), tbs.getSerialNumber().getValue());
        return new SignerIdentifier(encSid);
    }

    /**
     * Sacado de http://www.nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/
     * Checks whether given X.509 certificate is self-signed.
     */
    public static boolean isSelfSigned(X509Certificate cert) throws Exception {
        try {
            // Try to verify certificate signature with its own public key
            PublicKey key = (PublicKey) cert.getPublicKey();
            cert.verify(key);
            return true;
        } catch (Exception keyEx) {
            // Invalid key > not self-signed
            return false;
        }
    }

    public static String getHashBase64(String origStr, String digestAlgorithm) throws NoSuchAlgorithmException {
        MessageDigest sha = MessageDigest.getInstance(digestAlgorithm);
        byte[] resultDigest = sha.digest(origStr.getBytes());
        return DatatypeConverter.printBase64Binary(resultDigest);
    }

    public static DERObject getSingleValuedSignedAttribute(AttributeTable signedAttrTable,
            DERObjectIdentifier attrOID, String printableName) throws CMSException {
        if (signedAttrTable == null)
            return null;
        ASN1EncodableVector vector = signedAttrTable.getAll(attrOID);
        switch (vector.size()) {
        case 0:
            return null;
        case 1:
            Attribute t = (Attribute) vector.get(0);
            ASN1Set attrValues = t.getAttrValues();
            if (attrValues.size() != 1)
                throw new CMSException("A " + printableName + " attribute MUST have a single attribute value");
            return attrValues.getObjectAt(0).getDERObject();
        default:
            throw new CMSException(
                    "The SignedAttributes in a signerInfo MUST NOT include multiple instances of the "
                            + printableName + " attribute");
        }
    }

    public static byte[] getSignerDigest(SignerInformation signer) throws CMSException {
        DERObject derObject = CMSUtils.getSingleValuedSignedAttribute(signer.getSignedAttributes(),
                CMSAttributes.messageDigest, "message-digest");
        ASN1OctetString signedMessageDigest = (ASN1OctetString) derObject;
        return signedMessageDigest.getOctets();
    }

    public static String getDigestId(String digestAlgOID) {
        if (DIGEST_SHA1.equals(digestAlgOID))
            return "SHA1";
        if (DIGEST_SHA224.equals(digestAlgOID))
            return "SHA224";
        if (DIGEST_SHA256.equals(digestAlgOID))
            return "SHA256";
        if (DIGEST_SHA384.equals(digestAlgOID))
            return "SHA384";
        if (DIGEST_SHA512.equals(digestAlgOID))
            return "SHA512";
        if (DIGEST_MD5.equals(digestAlgOID))
            return "MD5";
        if (DIGEST_GOST3411.equals(digestAlgOID))
            return "GOST3411";
        if (DIGEST_RIPEMD128.equals(digestAlgOID))
            return "RIPEMD128";
        if (DIGEST_RIPEMD160.equals(digestAlgOID))
            return "RIPEMD160";
        if (DIGEST_RIPEMD256.equals(digestAlgOID))
            return "RIPEMD256";
        return null;
    }

    public static String getEncryptiontId(String encryptionAlgOID) {
        if (ENCRYPTION_RSA.equals(encryptionAlgOID))
            return "RSA";
        if (ENCRYPTION_DSA.equals(encryptionAlgOID))
            return "DSA";
        if (ENCRYPTION_ECDSA.equals(encryptionAlgOID))
            return "ECDSA";
        if (ENCRYPTION_RSA_PSS.equals(encryptionAlgOID))
            return "RSA_PSS";
        if (ENCRYPTION_GOST3410.equals(encryptionAlgOID))
            return "GOST3410";
        if (ENCRYPTION_ECGOST3410.equals(encryptionAlgOID))
            return "ECGOST3410";
        return null;
    }

    public static AlgorithmIdentifier fixAlgID(AlgorithmIdentifier algId) {
        if (algId.getParameters() == null) {
            return new AlgorithmIdentifier(algId.getObjectId(), DERNull.INSTANCE);
        }
        return algId;
    }

    public static byte[] getDigestToken(TimeStampToken timeStampToken) {
        if (timeStampToken == null)
            return null;
        CMSSignedData tokenCMSSignedData = timeStampToken.toCMSSignedData();
        Collection signers = tokenCMSSignedData.getSignerInfos().getSigners();
        SignerInformation tsaSignerInfo = (SignerInformation) signers.iterator().next();

        AttributeTable signedAttrTable = tsaSignerInfo.getSignedAttributes();
        ASN1EncodableVector v = signedAttrTable.getAll(CMSAttributes.messageDigest);
        Attribute t = (Attribute) v.get(0);
        ASN1Set attrValues = t.getAttrValues();
        DERObject validMessageDigest = attrValues.getObjectAt(0).getDERObject();

        ASN1OctetString signedMessageDigest = (ASN1OctetString) validMessageDigest;
        byte[] digestToken = signedMessageDigest.getOctets();
        //String digestTokenStr = new String(Base64.encode(digestToken));
        return digestToken;
    }

}