Java tutorial
/************************************************************************* * * * EJBCA: The OpenSource Certificate Authority * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package org.ejbca.extra.db; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.PrivateKey; import java.security.cert.CertPath; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; import java.security.cert.CertStore; import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.bouncycastle.cms.CMSEnvelopedData; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSSignedDataGenerator; import org.bouncycastle.cms.CMSSignedGenerator; import org.bouncycastle.cms.RecipientInformation; import org.bouncycastle.cms.RecipientInformationStore; import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.SignerInformationStore; /** * Class containing static help methods used to encrypt, decrypt, sign and verify ExtRASubMessages * * @author philip * $Id: ExtRAMsgHelper.java 9330 2010-06-30 18:16:53Z anatom $ */ public class ExtRAMsgHelper { private static final Log log = LogFactory.getLog(ExtRAMsgHelper.class); private static String provider = "BC"; // default provider private static String encAlg = CMSEnvelopedDataGenerator.AES256_CBC; // default encryption algorithm private static String signAlg = CMSSignedGenerator.DIGEST_SHA256; // default signature digest /** * Method to initalize the helper class. Should be called before any of the methods are used * in not hte default values should be used. * * @param provider provider to use "BC" is default. * @param encAlg encryption algorithm to use, must be supproted by the specified provider. * @prarm signAlg signature algorighm to use, must be supproted by the specified provider. */ public static void init(String provider, String encAlg, String signAlg) { ExtRAMsgHelper.provider = provider; ExtRAMsgHelper.encAlg = encAlg; ExtRAMsgHelper.signAlg = signAlg; } /** * Method that should be used to encrypt data in a message. * * Uses the algorithm specified in the init method. * * @param encCert, the recepient to encrypt to. * @param data * @return encrypted byte[] * @throws IOException */ public static byte[] encryptData(X509Certificate encCert, byte[] data) throws IOException { CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); CMSEnvelopedData ed; try { edGen.addKeyTransRecipient(encCert); ed = edGen.generate(new CMSProcessableByteArray(data), encAlg, provider); } catch (Exception e) { log.error("Error Encryotin Keys:: ", e); throw new IOException(e.getMessage()); } return ed.getEncoded(); } /** * Method that should be used to decrypt data in a message. * * Uses the algorithm specified in the init method. * * @param decKey, the recipients private key. * @param encData, the encrypted data * @return encrypted byte[] or null if decryption failed. */ public static byte[] decryptData(PrivateKey decKey, byte[] encData) { byte[] retdata = null; try { CMSEnvelopedData ed = new CMSEnvelopedData(encData); RecipientInformationStore recipients = ed.getRecipientInfos(); Iterator it = recipients.getRecipients().iterator(); RecipientInformation recipient = (RecipientInformation) it.next(); retdata = recipient.getContent(decKey, provider); } catch (Exception e) { log.error("Error decypting data : ", e); } return retdata; } /** * Method that signes the given data using the algorithm specified in the init method. * * @param signKey, the key used to sign the data * @param signCert the certificate * @param data * @return the signed data or null if signature failed */ public static byte[] signData(PrivateKey signKey, X509Certificate signCert, byte[] data) { byte[] retdata = null; try { ArrayList certList = new ArrayList(); certList.add(signCert); CertStore certs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), provider); CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); gen.addCertificatesAndCRLs(certs); gen.addSigner(signKey, signCert, signAlg); CMSSignedData signedData = gen.generate(new CMSProcessableByteArray(data), true, provider); retdata = signedData.getEncoded(); } catch (Exception e) { log.error("Error signing data : ", e); } return retdata; } /** * Method used to verify signed data. * * @param TrustedCACerts a Collection of trusted certifcates, should contain the entire chains * @param TrustedCRLs a Collection of trusted CRLS, use null if no CRL check should be used. * @param signedData the data to verify * @return true if signature verifes */ public static ParsedSignatureResult verifySignature(Collection cACertChain, Collection trustedCRLs, byte[] signedData) { return verifySignature(cACertChain, trustedCRLs, signedData, new Date()); } /** * Method used to verify signed data. * * @param TrustedCACerts a Collection of trusted certificates, should contain the entire chains * @param TrustedCRLs a Collection of trusted CRLS, use null if no CRL check should be used. * @param signedData the data to verify * @param date the date used to check the validity against. * @return a ParsedSignatureResult. */ public static ParsedSignatureResult verifySignature(Collection cACertChain, Collection trustedCRLs, byte[] signedData, Date date) { boolean verifies = false; X509Certificate usercert = null; ParsedSignatureResult retval = new ParsedSignatureResult(false, null, null); byte[] content = null; try { // First verify the signature CMSSignedData sp = new CMSSignedData(signedData); CertStore certs = sp.getCertificatesAndCRLs("Collection", "BC"); SignerInformationStore signers = sp.getSignerInfos(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ((CMSProcessableByteArray) sp.getSignedContent()).write(baos); content = baos.toByteArray(); baos.close(); Collection c = signers.getSigners(); Iterator it = c.iterator(); while (it.hasNext()) { SignerInformation signer = (SignerInformation) it.next(); Collection certCollection = certs.getCertificates(signer.getSID()); Iterator certIt = certCollection.iterator(); usercert = (X509Certificate) certIt.next(); boolean validalg = signer.getDigestAlgOID().equals(signAlg); verifies = validalg && signer.verify(usercert.getPublicKey(), "BC"); } // Second validate the certificate X509Certificate rootCert = null; Iterator iter = cACertChain.iterator(); while (iter.hasNext()) { X509Certificate cert = (X509Certificate) iter.next(); if (cert.getIssuerDN().equals(cert.getSubjectDN())) { rootCert = cert; break; } } if (rootCert == null) { throw new CertPathValidatorException("Error Root CA cert not found in cACertChain"); } List list = new ArrayList(); list.add(usercert); list.add(cACertChain); if (trustedCRLs != null) { list.add(trustedCRLs); } CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list); CertStore store = CertStore.getInstance("Collection", ccsp); //validating path List certchain = new ArrayList(); certchain.addAll(cACertChain); certchain.add(usercert); CertPath cp = CertificateFactory.getInstance("X.509", "BC").generateCertPath(certchain); Set trust = new HashSet(); trust.add(new TrustAnchor(rootCert, null)); CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC"); PKIXParameters param = new PKIXParameters(trust); param.addCertStore(store); param.setDate(date); if (trustedCRLs == null) { param.setRevocationEnabled(false); } else { param.setRevocationEnabled(true); } cpv.validate(cp, param); retval = new ParsedSignatureResult(verifies, usercert, content); } catch (Exception e) { log.error("Error verifying data : ", e); } return retval; } }