Package org.ejbca.core.protocol.scep

Source Code of org.ejbca.core.protocol.scep.ScepRequestGenerator

package org.ejbca.core.protocol.scep;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.smime.SMIMECapability;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.ejbca.core.model.AlgorithmConstants;
import org.ejbca.util.Base64;
import org.ejbca.util.CertTools;

/** Class used to generate SCEP messages. Used for SCEP clients and testing
*
* @author tomas
* @version $Id: ScepRequestGenerator.java 8745 2010-03-15 14:00:15Z primelars $
*/
public class ScepRequestGenerator {
    private static Logger log = Logger.getLogger(ScepRequestGenerator.class);

    private X509Certificate cert = null;
    private X509Certificate cacert = null;
    private String reqdn = null;
    private KeyPair keys = null;
    private String digestOid = CMSSignedGenerator.DIGEST_SHA1;
    private PKCS10CertificationRequest p10request;
    private String senderNonce = null;

    /** A good random source for nounces, can take a long time to initialize on vmware */
    private static SecureRandom randomSource = null;

    public ScepRequestGenerator() {
      try {
        if (randomSource == null) {
            randomSource = SecureRandom.getInstance("SHA1PRNG");         
        }
      } catch (Exception e) {
        log.error(e);
      }
    }
   
    public void setKeys(KeyPair myKeys) {
        this.keys = myKeys;
    }
    public void setDigestOid(String oid) {
      digestOid = oid;
    }
    /** Base 64 encode senderNonce
     */
    public String getSenderNonce() {
        return senderNonce;
    }

    public byte[] generateCrlReq(String dn, String transactionId, X509Certificate ca) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException, CMSException, InvalidAlgorithmParameterException, CertStoreException, CertificateEncodingException, IllegalStateException {
        this.cacert = ca;
        this.reqdn = dn;
        X509Name name = CertTools.stringToBcX509Name(cacert.getIssuerDN().getName());
        IssuerAndSerialNumber ias = new IssuerAndSerialNumber(name, cacert.getSerialNumber());
        // Create self signed cert, validity 1 day
        cert = CertTools.genSelfCert(reqdn,24*60*60*1000,null,keys.getPrivate(),keys.getPublic(),AlgorithmConstants.SIGALG_SHA1_WITH_RSA,false);
       
        // wrap message in pkcs#7
        byte[] msg = wrap(ias.getEncoded(), "22", transactionId);       
        return msg;
    }
    public byte[] generateCertReq(String dn, String password, String transactionId, X509Certificate ca) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException, CMSException, InvalidAlgorithmParameterException, CertStoreException, CertificateEncodingException, IllegalStateException {
        // Extension request attribute is a set of X509Extensions
        // ASN1EncodableVector x509extensions = new ASN1EncodableVector();
        // An X509Extensions is a sequence of Extension which is a sequence of {oid, X509Extension}
        final Vector<DERObjectIdentifier> oidvec = new Vector<DERObjectIdentifier>();
        final Vector<X509Extension> valuevec = new Vector<X509Extension>();
        // Requested extensions attribute
        // AltNames
        final GeneralNames san = CertTools.getGeneralNamesFromAltName("dNSName=foo.bar.com,iPAddress=10.0.0.1");
        final ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        final DEROutputStream dOut = new DEROutputStream(bOut);
        try {
            dOut.writeObject(san);
        } catch (IOException e) {
            throw new IllegalArgumentException("error encoding value: " + e);
        }
        valuevec.add(new X509Extension(false, new DEROctetString(bOut.toByteArray())));
        oidvec.add(X509Extensions.SubjectAlternativeName);
        return generateCertReq( dn, password, transactionId, ca, new X509Extensions(oidvec,valuevec) );
    }
    public byte[] generateCertReq(String dn, String password, String transactionId, X509Certificate ca, X509Extensions exts) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException, CMSException, InvalidAlgorithmParameterException, CertStoreException, CertificateEncodingException, IllegalStateException {
        this.cacert = ca;
        this.reqdn = dn;
        // Generate keys

        // Create challenge password attribute for PKCS10
        // Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
        //
        // Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
        //    type    ATTRIBUTE.&id({IOSet}),
        //    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
        // }
        ASN1EncodableVector challpwdattr = new ASN1EncodableVector();
        // Challenge password attribute
        challpwdattr.add(PKCSObjectIdentifiers.pkcs_9_at_challengePassword);
        ASN1EncodableVector pwdvalues = new ASN1EncodableVector();
        pwdvalues.add(new DERUTF8String(password));
        challpwdattr.add(new DERSet(pwdvalues));
        ASN1EncodableVector extensionattr = new ASN1EncodableVector();
        extensionattr.add(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest);
        extensionattr.add(new DERSet(exts));
        // Complete the Attribute section of the request, the set (Attributes) contains two sequences (Attribute)
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(new DERSequence(challpwdattr));
        v.add(new DERSequence(extensionattr));
        DERSet attributes = new DERSet(v);
        // Create PKCS#10 certificate request
        this.p10request = new PKCS10CertificationRequest("SHA1WithRSA",
                CertTools.stringToBcX509Name(reqdn), keys.getPublic(), attributes, keys.getPrivate());
       
        // Create self signed cert, validity 1 day
        this.cert = CertTools.genSelfCert(reqdn,24*60*60*1000,null,keys.getPrivate(),keys.getPublic(),AlgorithmConstants.SIGALG_SHA1_WITH_RSA,false);
       
        // wrap message in pkcs#7
        byte[] msg = wrap(p10request.getEncoded(), "19", transactionId);
        return msg;       
    }
   
    public byte[] generateGetCertInitial(String dn, String transactionId, X509Certificate ca) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CertStoreException, IOException, CMSException  {
        this.cacert = ca;
        this.reqdn = dn;

        // pkcsGetCertInitial issuerAndSubject ::= {
        //      issuer "the certificate authority issuer name"
        //      subject "the requester subject name as given in PKCS#10"
        //  }
        ASN1EncodableVector vec = new ASN1EncodableVector();
        vec.add(new DERUTF8String(ca.getIssuerDN().getName()));
        vec.add(new DERUTF8String(dn));
        DERSequence seq = new DERSequence(vec);
       
        // The self signed certificate has already been generated when the request message was created
        // Create self signed cert, validity 1 day
        //cert = CertTools.genSelfCert(reqdn,24*60*60*1000,null,keys.getPrivate(),keys.getPublic(),AlgorithmConstants.SIGALG_SHA1_WITH_RSA,false);
       
        // wrap message in pkcs#7
        byte[] msg = wrap(seq.getEncoded(), "20", transactionId);
        return msg;       
    }
   
    private CMSEnvelopedData envelope(CMSProcessable envThis) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException {
        CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
        // Envelope the CMS message
        edGen.addKeyTransRecipient(cacert);
        CMSEnvelopedData ed = edGen.generate(envThis, SMIMECapability.dES_CBC.getId(), "BC");
        return ed;
    }
    private CMSSignedData sign(CMSProcessable signThis, String messageType, String transactionId) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException, InvalidAlgorithmParameterException, CertStoreException {
        CMSSignedDataGenerator gen1 = new CMSSignedDataGenerator();

        // add authenticated attributes...status, transactionId, sender- and more...
        Hashtable attributes = new Hashtable();
        DERObjectIdentifier oid;
        Attribute attr;
        DERSet value;
       
        // Message type (certreq)
        oid = new DERObjectIdentifier(ScepRequestMessage.id_messageType);
        value = new DERSet(new DERPrintableString(messageType));
        attr = new Attribute(oid, value);
        attributes.put(attr.getAttrType(), attr);

        // TransactionId
        oid = new DERObjectIdentifier(ScepRequestMessage.id_transId);
        value = new DERSet(new DERPrintableString(transactionId));
        attr = new Attribute(oid, value);
        attributes.put(attr.getAttrType(), attr);

        // senderNonce
        byte[] nonce = new byte[16];
        randomSource.nextBytes(nonce);
        senderNonce = new String(Base64.encode(nonce));
        if (nonce != null) {
            oid = new DERObjectIdentifier(ScepRequestMessage.id_senderNonce);
            log.debug("Added senderNonce: " + senderNonce);
            value = new DERSet(new DEROctetString(nonce));
            attr = new Attribute(oid, value);
            attributes.put(attr.getAttrType(), attr);
        }

        // Add our signer info and sign the message
        ArrayList certList = new ArrayList();
        certList.add(cert);
        CertStore certs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC");
        gen1.addCertificatesAndCRLs(certs);
        gen1.addSigner(keys.getPrivate(), cert, digestOid,
                new AttributeTable(attributes), null);
        // The signed data to be enveloped
        CMSSignedData s = gen1.generate(signThis, true, "BC");
        return s;
    }
    private byte[] wrap(byte[] envBytes, String messageType, String transactionId) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, CMSException, InvalidAlgorithmParameterException, CertStoreException {

        //
        // Create inner enveloped data
        //
        CMSEnvelopedData ed = envelope(new CMSProcessableByteArray(envBytes));
        log.debug("Enveloped data is " + ed.getEncoded().length + " bytes long");
        CMSProcessable msg = new CMSProcessableByteArray(ed.getEncoded());
        //
        // Create the outer signed data
        //
        CMSSignedData s = sign(msg, messageType, transactionId);
       
        byte[] ret = s.getEncoded();
        return ret;
       
    }
}
TOP

Related Classes of org.ejbca.core.protocol.scep.ScepRequestGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.