Example usage for org.bouncycastle.asn1.cms CMSObjectIdentifiers signedData

List of usage examples for org.bouncycastle.asn1.cms CMSObjectIdentifiers signedData

Introduction

In this page you can find the example usage for org.bouncycastle.asn1.cms CMSObjectIdentifiers signedData.

Prototype

ASN1ObjectIdentifier signedData

To view the source code for org.bouncycastle.asn1.cms CMSObjectIdentifiers signedData.

Click Source Link

Document

PKCS#7: 1.2.840.113549.1.7.2

Usage

From source file:dorkbox.util.crypto.CryptoX509.java

License:Apache License

/**
 * Creates a NEW signature block that contains the pkcs7 (minus content, which is the .SF file)
 * signature of the .SF file./* w ww  .j av a2s.com*/
 *
 * It contains the hash of the data, and the verification signature.
 */
public static byte[] createSignature(byte[] signatureSourceData, X509CertificateHolder x509CertificateHolder,
        AsymmetricKeyParameter privateKey) {

    try {
        CMSTypedData content = new CMSProcessableByteArray(signatureSourceData);

        ASN1ObjectIdentifier contentTypeOID = new ASN1ObjectIdentifier(content.getContentType().getId());
        ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
        ASN1EncodableVector signerInfos = new ASN1EncodableVector();

        AlgorithmIdentifier sigAlgId = x509CertificateHolder.getSignatureAlgorithm();
        AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);

        // use the bouncy-castle lightweight API to generate a hash of the signature source data (usually the signature file bytes)
        BcContentSignerBuilder contentSignerBuilder;
        AlgorithmIdentifier digEncryptionAlgorithm;

        if (privateKey instanceof ECPrivateKeyParameters) {
            contentSignerBuilder = new BcECDSAContentSignerBuilder(sigAlgId, digAlgId);
            digEncryptionAlgorithm = new AlgorithmIdentifier(DSAUtil.dsaOids[0], null); // 1.2.840.10040.4.1  // DSA hashID
        } else if (privateKey instanceof DSAPrivateKeyParameters) {
            contentSignerBuilder = new BcDSAContentSignerBuilder(sigAlgId, digAlgId);
            digEncryptionAlgorithm = new AlgorithmIdentifier(DSAUtil.dsaOids[0], null); // 1.2.840.10040.4.1  // DSA hashID
        } else if (privateKey instanceof RSAPrivateCrtKeyParameters) {
            contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
            digEncryptionAlgorithm = new AlgorithmIdentifier(RSAUtil.rsaOids[0], null); // 1.2.840.113549.1.1.1 // RSA hashID
        } else {
            throw new RuntimeException("Invalid signature type. Only ECDSA, DSA, RSA supported.");
        }

        ContentSigner hashSigner = contentSignerBuilder.build(privateKey);
        OutputStream outputStream = hashSigner.getOutputStream();
        outputStream.write(signatureSourceData, 0, signatureSourceData.length);
        outputStream.flush();
        byte[] sigBytes = hashSigner.getSignature();

        SignerIdentifier sigId = new SignerIdentifier(
                new IssuerAndSerialNumber(x509CertificateHolder.toASN1Structure()));

        SignerInfo inf = new SignerInfo(sigId, digAlgId, null, digEncryptionAlgorithm,
                new DEROctetString(sigBytes), (ASN1Set) null);

        digestAlgs.add(inf.getDigestAlgorithm());
        signerInfos.add(inf);

        ASN1EncodableVector certs = new ASN1EncodableVector();
        certs.add(x509CertificateHolder.toASN1Structure());

        ContentInfo encInfo = new ContentInfo(contentTypeOID, null);
        SignedData sd = new SignedData(new DERSet(digestAlgs), encInfo, new BERSet(certs), null,
                new DERSet(signerInfos));

        ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.signedData, sd);
        CMSSignedData cmsSignedData2 = new CMSSignedData(content, contentInfo);

        return cmsSignedData2.getEncoded();
    } catch (Throwable t) {
        logger.error("Error signing data.", t);
        throw new RuntimeException("Error trying to sign data. " + t.getMessage());
    }
}

From source file:mitm.common.security.cms.CMSContentTypeClassifier.java

License:Open Source License

/**
 * Returns the CMS content type of the provided sequence.
 * /*w w  w.  ja v  a  2 s .c  o m*/
 * See RFC3852 for content types
 * 
 * @param sequenceParser
 * @return
 */
public static CMSContentType getContentType(ASN1SequenceParser sequenceParser) {
    CMSContentType contentType = CMSContentType.UNKNOWN;

    try {
        ContentInfoParser contentInfoParser = new ContentInfoParser(sequenceParser);

        DERObjectIdentifier derContentType = contentInfoParser.getContentType();

        if (CMSObjectIdentifiers.data.equals(derContentType)) {
            contentType = CMSContentType.DATA;
        } else if (CMSObjectIdentifiers.signedData.equals(derContentType)) {
            contentType = CMSContentType.SIGNEDDATA;
        } else if (CMSObjectIdentifiers.envelopedData.equals(derContentType)) {
            contentType = CMSContentType.ENVELOPEDDATA;
        } else if (CMSObjectIdentifiers.signedAndEnvelopedData.equals(derContentType)) {
            contentType = CMSContentType.SIGNEDANDENVELOPEDDATA;
        } else if (CMSObjectIdentifiers.digestedData.equals(derContentType)) {
            contentType = CMSContentType.DIGESTEDDATA;
        } else if (CMSObjectIdentifiers.encryptedData.equals(derContentType)) {
            contentType = CMSContentType.ENCRYPTEDDATA;
        } else if (CMSObjectIdentifiers.compressedData.equals(derContentType)) {
            contentType = CMSContentType.COMPRESSEDDATA;
        }
    } catch (IOException e) {
        logger.error("IOException retrieving CMS content type", e);
    }
    return contentType;
}

From source file:net.jsign.asn1.authenticode.AuthenticodeSignedDataGenerator.java

License:Apache License

public CMSSignedData generate(ASN1ObjectIdentifier contentTypeOID, ASN1Encodable content)
        throws CMSException, IOException {
    digests.clear();//from   w w  w  . j  a  v  a 2 s.co  m

    SignerInfo signerInfo;

    if (!_signers.isEmpty()) {
        signerInfo = ((SignerInformation) _signers.get(0)).toASN1Structure();
    } else {
        SignerInfoGenerator signerInfoGenerator = (SignerInfoGenerator) signerGens.get(0);

        byte[] signedContent = content.toASN1Primitive().getEncoded("DER");

        OutputStream out = signerInfoGenerator.getCalculatingOutputStream();
        out.write(signedContent, 2, signedContent.length - 2); // skip the first 2 bytes as specified
        out.flush();
        out.close();

        signerInfo = signerInfoGenerator.generate(contentTypeOID);

        byte[] calculatedDigest = signerInfoGenerator.getCalculatedDigest();
        digests.put(signerInfoGenerator.getDigestAlgorithm().getAlgorithm().getId(), calculatedDigest);
    }

    ContentInfo encInfo = new ContentInfo(contentTypeOID, content);
    ASN1Set certificates = new DERSet((ASN1Encodable[]) certs.toArray(new ASN1Encodable[0]));

    ASN1Encodable signedData = new AuthenticodeSignedData(signerInfo.getDigestAlgorithm(), encInfo,
            certificates, signerInfo);

    ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.signedData, signedData);

    return new CMSSignedData(
            new CMSProcessableByteArray(contentTypeOID, content.toASN1Primitive().getEncoded("DER")),
            contentInfo);
}

From source file:org.codice.ddf.security.certificate.keystore.editor.KeystoreEditor.java

License:Open Source License

private synchronized void addToStore(String alias, String keyPassword, String storePassword, String data,
        String type, String fileName, String path, String storepass, KeyStore store)
        throws KeystoreEditorException {
    OutputStream fos = null;//from w  ww  .  jav  a  2s . c  o m
    try (InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(data))) {
        if (StringUtils.isBlank(alias)) {
            throw new IllegalArgumentException("Alias cannot be null.");
        }
        Path storeFile = Paths.get(path);
        //check the two most common key/cert stores first (pkcs12 and jks)
        if (PKCS12_TYPE.equals(type) || StringUtils.endsWithIgnoreCase(fileName, ".p12")) {
            //priv key + cert chain
            KeyStore pkcs12Store = KeyStore.getInstance("PKCS12");
            pkcs12Store.load(inputStream, storePassword.toCharArray());
            Certificate[] chain = pkcs12Store.getCertificateChain(alias);
            Key key = pkcs12Store.getKey(alias, keyPassword.toCharArray());
            if (key != null) {
                store.setKeyEntry(alias, key, keyPassword.toCharArray(), chain);
                fos = Files.newOutputStream(storeFile);
                store.store(fos, storepass.toCharArray());
            }
        } else if (JKS_TYPE.equals(type) || StringUtils.endsWithIgnoreCase(fileName, ".jks")) {
            //java keystore file
            KeyStore jks = KeyStore.getInstance("jks");
            jks.load(inputStream, storePassword.toCharArray());
            Enumeration<String> aliases = jks.aliases();

            //we are going to store all entries from the jks regardless of the passed in alias
            while (aliases.hasMoreElements()) {
                String jksAlias = aliases.nextElement();

                if (jks.isKeyEntry(jksAlias)) {
                    Key key = jks.getKey(jksAlias, keyPassword.toCharArray());
                    Certificate[] certificateChain = jks.getCertificateChain(jksAlias);
                    store.setKeyEntry(jksAlias, key, keyPassword.toCharArray(), certificateChain);
                } else {
                    Certificate certificate = jks.getCertificate(jksAlias);
                    store.setCertificateEntry(jksAlias, certificate);
                }
            }

            fos = Files.newOutputStream(storeFile);
            store.store(fos, storepass.toCharArray());
            //need to parse der separately from pem, der has the same mime type but is binary hence checking both
        } else if (DER_TYPE.equals(type) && StringUtils.endsWithIgnoreCase(fileName, ".der")) {
            ASN1InputStream asn1InputStream = new ASN1InputStream(inputStream);
            ASN1Primitive asn1Primitive = asn1InputStream.readObject();
            X509CertificateHolder x509CertificateHolder = new X509CertificateHolder(asn1Primitive.getEncoded());
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
            Certificate certificate = certificateFactory
                    .generateCertificate(new ByteArrayInputStream(x509CertificateHolder.getEncoded()));
            X500Name x500name = new JcaX509CertificateHolder((X509Certificate) certificate).getSubject();
            RDN cn = x500name.getRDNs(BCStyle.CN)[0];
            String cnStr = IETFUtils.valueToString(cn.getFirst().getValue());
            if (!store.isCertificateEntry(cnStr) && !store.isKeyEntry(cnStr)) {
                store.setCertificateEntry(cnStr, certificate);
            }
            store.setCertificateEntry(alias, certificate);
            fos = Files.newOutputStream(storeFile);
            store.store(fos, storepass.toCharArray());
            //if it isn't one of the stores we support, it might be a key or cert by itself
        } else if (isPemParsable(type, fileName)) {
            //This is the catch all case for PEM, P7B, etc. with common file extensions if the mime type isn't read correctly in the browser
            Reader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            PEMParser pemParser = new PEMParser(reader);
            Object object;
            boolean setEntry = false;
            while ((object = pemParser.readObject()) != null) {
                if (object instanceof PEMEncryptedKeyPair || object instanceof PEMKeyPair) {
                    PEMKeyPair pemKeyPair;
                    if (object instanceof PEMEncryptedKeyPair) {
                        PEMEncryptedKeyPair pemEncryptedKeyPairKeyPair = (PEMEncryptedKeyPair) object;
                        JcePEMDecryptorProviderBuilder jcePEMDecryptorProviderBuilder = new JcePEMDecryptorProviderBuilder();
                        pemKeyPair = pemEncryptedKeyPairKeyPair.decryptKeyPair(
                                jcePEMDecryptorProviderBuilder.build(keyPassword.toCharArray()));
                    } else {
                        pemKeyPair = (PEMKeyPair) object;
                    }

                    KeyPair keyPair = new JcaPEMKeyConverter().setProvider("BC").getKeyPair(pemKeyPair);
                    PrivateKey privateKey = keyPair.getPrivate();
                    Certificate[] chain = store.getCertificateChain(alias);
                    if (chain == null) {
                        chain = buildCertChain(alias, store);
                    }
                    store.setKeyEntry(alias, privateKey, keyPassword.toCharArray(), chain);
                    setEntry = true;
                } else if (object instanceof X509CertificateHolder) {
                    X509CertificateHolder x509CertificateHolder = (X509CertificateHolder) object;
                    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
                    Certificate certificate = certificateFactory
                            .generateCertificate(new ByteArrayInputStream(x509CertificateHolder.getEncoded()));
                    X500Name x500name = new JcaX509CertificateHolder((X509Certificate) certificate)
                            .getSubject();
                    RDN cn = x500name.getRDNs(BCStyle.CN)[0];
                    String cnStr = IETFUtils.valueToString(cn.getFirst().getValue());
                    if (!store.isCertificateEntry(cnStr) && !store.isKeyEntry(cnStr)) {
                        store.setCertificateEntry(cnStr, certificate);
                    }
                    store.setCertificateEntry(alias, certificate);
                    setEntry = true;
                } else if (object instanceof ContentInfo) {
                    ContentInfo contentInfo = (ContentInfo) object;
                    if (contentInfo.getContentType().equals(CMSObjectIdentifiers.envelopedData)) {
                        CMSEnvelopedData cmsEnvelopedData = new CMSEnvelopedData(contentInfo);
                        OriginatorInfo originatorInfo = cmsEnvelopedData.getOriginatorInfo().toASN1Structure();
                        ASN1Set certificates = originatorInfo.getCertificates();
                        setEntry = importASN1CertificatesToStore(store, setEntry, certificates);
                    } else if (contentInfo.getContentType().equals(CMSObjectIdentifiers.signedData)) {
                        SignedData signedData = SignedData.getInstance(contentInfo.getContent());
                        ASN1Set certificates = signedData.getCertificates();
                        setEntry = importASN1CertificatesToStore(store, setEntry, certificates);
                    }
                } else if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
                    PKCS8EncryptedPrivateKeyInfo pkcs8EncryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) object;
                    Certificate[] chain = store.getCertificateChain(alias);
                    if (chain == null) {
                        chain = buildCertChain(alias, store);
                    }
                    try {
                        store.setKeyEntry(alias, pkcs8EncryptedPrivateKeyInfo.getEncoded(), chain);
                        setEntry = true;
                    } catch (KeyStoreException keyEx) {
                        try {
                            PKCS8Key pkcs8Key = new PKCS8Key(pkcs8EncryptedPrivateKeyInfo.getEncoded(),
                                    keyPassword.toCharArray());
                            store.setKeyEntry(alias, pkcs8Key.getPrivateKey(), keyPassword.toCharArray(),
                                    chain);
                            setEntry = true;
                        } catch (GeneralSecurityException e) {
                            LOGGER.info(
                                    "Unable to add PKCS8 key to keystore with secondary method. Throwing original exception.",
                                    e);
                            throw keyEx;
                        }
                    }
                }
            }
            if (setEntry) {
                fos = Files.newOutputStream(storeFile);
                store.store(fos, storepass.toCharArray());
            }
        }
    } catch (Exception e) {
        LOGGER.info("Unable to add entry {} to store", alias, e);
        throw new KeystoreEditorException("Unable to add entry " + alias + " to store", e);
    } finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException ignore) {
            }
        }
    }
    init();
}

From source file:org.ejbca.core.protocol.scep.ScepRequestMessage.java

License:Open Source License

private void init() throws IOException {
    if (log.isTraceEnabled()) {
        log.trace(">init");
    }// w  ww.  j ava 2  s  . co m
    try {
        CMSSignedData csd = new CMSSignedData(scepmsg);
        SignerInformationStore infoStore = csd.getSignerInfos();
        @SuppressWarnings("unchecked")
        Collection<SignerInformation> signers = infoStore.getSigners();
        Iterator<SignerInformation> iter = signers.iterator();
        if (iter.hasNext()) {
            SignerInformation si = (SignerInformation) iter.next();
            preferredDigestAlg = si.getDigestAlgOID();
            log.debug("Set " + preferredDigestAlg + " as preferred digest algorithm for SCEP");
        }
    } catch (CMSException e) {
        // ignore, use default digest algo
        log.error("CMSException trying to get preferred digest algorithm: ", e);
    }
    // Parse and verify the integrity of the PKIOperation message PKCS#7
    /* If this would have been done using the newer CMS it would have made me so much happier... */
    ASN1InputStream seqAsn1InputStream = new ASN1InputStream(new ByteArrayInputStream(scepmsg));
    ASN1Sequence seq = null;
    try {
        seq = (ASN1Sequence) seqAsn1InputStream.readObject();
    } finally {
        seqAsn1InputStream.close();
    }
    ContentInfo ci = ContentInfo.getInstance(seq);
    String ctoid = ci.getContentType().getId();

    if (ctoid.equals(CMSObjectIdentifiers.signedData.getId())) {
        // This is SignedData so it is a pkcsCertReqSigned, pkcsGetCertInitialSigned, pkcsGetCertSigned, pkcsGetCRLSigned
        // (could also be pkcsRepSigned or certOnly, but we don't receive them on the server side
        // Try to find out what kind of message this is
        sd = SignedData.getInstance((ASN1Sequence) ci.getContent());
        // Get self signed cert to identify the senders public key
        ASN1Set certs = sd.getCertificates();
        if (certs.size() > 0) {
            // There should be only one...
            ASN1Encodable dercert = certs.getObjectAt(0);
            if (dercert != null) {
                // Requester's self-signed certificate is requestKeyInfo
                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
                DEROutputStream dOut = new DEROutputStream(bOut);
                dOut.writeObject(dercert);
                if (bOut.size() > 0) {
                    requestKeyInfo = bOut.toByteArray();
                    //Create Certificate used for debugging
                    try {
                        signercert = CertTools.getCertfromByteArray(requestKeyInfo);
                        if (log.isDebugEnabled()) {
                            log.debug("requestKeyInfo is SubjectDN: " + CertTools.getSubjectDN(signercert)
                                    + ", Serial=" + CertTools.getSerialNumberAsString(signercert)
                                    + "; IssuerDN: " + CertTools.getIssuerDN(signercert).toString());
                        }
                    } catch (CertificateException e) {
                        log.error("Error parsing requestKeyInfo : ", e);
                    }

                }
            }
        }

        Enumeration<?> sis = sd.getSignerInfos().getObjects();

        if (sis.hasMoreElements()) {
            SignerInfo si = SignerInfo.getInstance((ASN1Sequence) sis.nextElement());
            Enumeration<?> attr = si.getAuthenticatedAttributes().getObjects();

            while (attr.hasMoreElements()) {
                Attribute a = Attribute.getInstance((ASN1Sequence) attr.nextElement());
                if (log.isDebugEnabled()) {
                    log.debug("Found attribute: " + a.getAttrType().getId());
                }
                if (a.getAttrType().getId().equals(id_senderNonce)) {
                    Enumeration<?> values = a.getAttrValues().getObjects();
                    ASN1OctetString str = ASN1OctetString.getInstance(values.nextElement());
                    senderNonce = new String(Base64.encode(str.getOctets(), false));
                    if (log.isDebugEnabled()) {
                        log.debug("senderNonce = " + senderNonce);
                    }
                }
                if (a.getAttrType().getId().equals(id_transId)) {
                    Enumeration<?> values = a.getAttrValues().getObjects();
                    DERPrintableString str = DERPrintableString.getInstance(values.nextElement());
                    transactionId = str.getString();
                    if (log.isDebugEnabled()) {
                        log.debug("transactionId = " + transactionId);
                    }
                }
                if (a.getAttrType().getId().equals(id_messageType)) {
                    Enumeration<?> values = a.getAttrValues().getObjects();
                    DERPrintableString str = DERPrintableString.getInstance(values.nextElement());
                    messageType = Integer.parseInt(str.getString());
                    if (log.isDebugEnabled()) {
                        log.debug("messagetype = " + messageType);
                    }
                }
            }
        }

        // If this is a PKCSReq
        if ((messageType == ScepRequestMessage.SCEP_TYPE_PKCSREQ)
                || (messageType == ScepRequestMessage.SCEP_TYPE_GETCRL)
                || (messageType == ScepRequestMessage.SCEP_TYPE_GETCERTINITIAL)) {
            // Extract the contents, which is an encrypted PKCS10 if messageType == 19
            // , and an encrypted issuer and subject if messageType == 20 (not extracted)
            // and an encrypted IssuerAndSerialNumber if messageType == 22
            ci = sd.getEncapContentInfo();
            ctoid = ci.getContentType().getId();

            if (ctoid.equals(CMSObjectIdentifiers.data.getId())) {
                ASN1OctetString content = (ASN1OctetString) ci.getContent();
                if (log.isDebugEnabled()) {
                    log.debug("envelopedData is " + content.getOctets().length + " bytes.");
                }
                ASN1InputStream seq1Asn1InputStream = new ASN1InputStream(
                        new ByteArrayInputStream(content.getOctets()));
                ASN1Sequence seq1 = null;
                try {
                    seq1 = (ASN1Sequence) seq1Asn1InputStream.readObject();
                } finally {
                    seq1Asn1InputStream.close();
                }
                envEncData = ContentInfo.getInstance(seq1);
                ctoid = envEncData.getContentType().getId();

                if (ctoid.equals(CMSObjectIdentifiers.envelopedData.getId())) {
                    envData = EnvelopedData.getInstance((ASN1Sequence) envEncData.getContent());
                    ASN1Set recipientInfos = envData.getRecipientInfos();
                    Enumeration<?> e = recipientInfos.getObjects();
                    while (e.hasMoreElements()) {
                        RecipientInfo ri = RecipientInfo.getInstance(e.nextElement());
                        KeyTransRecipientInfo recipientInfo = KeyTransRecipientInfo.getInstance(ri.getInfo());
                        RecipientIdentifier rid = recipientInfo.getRecipientIdentifier();
                        IssuerAndSerialNumber iasn = IssuerAndSerialNumber.getInstance(rid.getId());
                        issuerDN = iasn.getName().toString();
                        serialNo = iasn.getSerialNumber().getValue();
                        if (log.isDebugEnabled()) {
                            log.debug("IssuerDN: " + issuerDN);
                            log.debug("SerialNumber: " + iasn.getSerialNumber().getValue().toString(16));
                        }
                    }
                } else {
                    errorText = "EncapsulatedContentInfo does not contain PKCS7 envelopedData: ";
                    log.error(errorText + ctoid);
                    error = 2;
                }
            } else {
                errorText = "EncapsulatedContentInfo is not of type 'data': ";
                log.error(errorText + ctoid);
                error = 3;
            }
        } else {
            errorText = "This is not a certification request!";
            log.error(errorText);
            error = 4;
        }
    } else {
        errorText = "PKCSReq does not contain 'signedData': ";
        log.error(errorText + ctoid);
        error = 1;
    }

    log.trace("<init");
}

From source file:org.votingsystem.signature.dnie.DNIePDFContentSigner.java

License:Open Source License

public CMSSignedData getCMSSignedData(String eContentType, CMSProcessable content, boolean encapsulate,
        Provider sigProvider, boolean addDefaultAttributes, List signerInfs) throws Exception {
    // TODO if (signerInfs.isEmpty()){
    //            /* RFC 3852 5.2
    //             * "In the degenerate case where there are no signers, the
    //             * EncapsulatedContentInfo value being "signed" is irrelevant.  In this
    //             * case, the content type within the EncapsulatedContentInfo value being
    //             * "signed" MUST be id-data (as defined in section 4), and the content
    //             * field of the EncapsulatedContentInfo value MUST be omitted."
    //             *//*from  www .  j a  va2  s .c o  m*/
    //            if (encapsulate) {
    //                throw new IllegalArgumentException("no signers, encapsulate must be false");
    //            } if (!DATA.equals(eContentType)) {
    //                throw new IllegalArgumentException("no signers, eContentType must be id-data");
    //            }
    //        }
    //        if (!DATA.equals(eContentType)) {
    //            /* RFC 3852 5.3
    //             * [The 'signedAttrs']...
    //             * field is optional, but it MUST be present if the content type of
    //             * the EncapsulatedContentInfo value being signed is not id-data.
    //             */
    //            // TODO signedAttrs must be present for all signers
    //        }
    ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
    ASN1EncodableVector signerInfos = new ASN1EncodableVector();
    digests.clear(); // clear the current preserved digest state
    Iterator it = _signers.iterator();
    while (it.hasNext()) {
        SignerInformation signer = (SignerInformation) it.next();
        digestAlgs.add(CMSUtils.fixAlgID(signer.getDigestAlgorithmID()));
        signerInfos.add(signer.toSignerInfo());
    }
    boolean isCounterSignature = (eContentType == null);
    ASN1ObjectIdentifier contentTypeOID = isCounterSignature ? CMSObjectIdentifiers.data
            : new ASN1ObjectIdentifier(eContentType);
    it = signerInfs.iterator();
    while (it.hasNext()) {
        SignerInf signer = (SignerInf) it.next();
        log.info("signer.signerIdentifier: " + signer.signerIdentifier.toASN1Object().toString());
        digestAlgs.add(signer.getDigestAlgorithmID());
        signerInfos.add(signer.toSignerInfo(contentTypeOID, content, rand, null, addDefaultAttributes,
                isCounterSignature));
    }
    ASN1Set certificates = null;
    if (!certs.isEmpty())
        certificates = CMSUtils.createBerSetFromList(certs);
    ASN1Set certrevlist = null;
    if (!crls.isEmpty())
        certrevlist = CMSUtils.createBerSetFromList(crls);
    ASN1OctetString octs = null;
    if (encapsulate && content != null) {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        content.write(bOut);
        octs = new BERConstructedOctetString(bOut.toByteArray());
    }
    ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
    SignedData sd = new SignedData(new DERSet(digestAlgs), encInfo, certificates, certrevlist,
            new DERSet(signerInfos));
    ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.signedData, sd);
    return new CMSSignedData(content, contentInfo);
}

From source file:org.votingsystem.signature.util.PDFContentSigner.java

License:Open Source License

public CMSSignedData getCMSSignedData(String eContentType, CMSProcessable content, boolean encapsulate,
        Provider sigProvider, boolean addDefaultAttributes, List<SignerInfo> signerInfoList)
        throws NoSuchAlgorithmException, CMSException, Exception {
    // TODO if (signerInfs.isEmpty()){
    //            /* RFC 3852 5.2
    //             * "In the degenerate case where there are no signers, the
    //             * EncapsulatedContentInfo value being "signed" is irrelevant.  In this
    //             * case, the content type within the EncapsulatedContentInfo value being
    //             * "signed" MUST be id-data (as defined in section 4), and the content
    //             * field of the EncapsulatedContentInfo value MUST be omitted."
    //             *///from  w w  w . j a v  a  2 s . c  o m
    //            if (encapsulate) {
    //                throw new IllegalArgumentException("no signers, encapsulate must be false");
    //            } if (!DATA.equals(eContentType)) {
    //                throw new IllegalArgumentException("no signers, eContentType must be id-data");
    //            }
    //        }
    //        if (!DATA.equals(eContentType)) {
    //            /* RFC 3852 5.3
    //             * [The 'signedAttrs']...
    //             * field is optional, but it MUST be present if the content type of
    //             * the EncapsulatedContentInfo value being signed is not id-data.
    //             */
    //            // TODO signedAttrs must be present for all signers
    //        }
    ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
    ASN1EncodableVector signerInfos = new ASN1EncodableVector();
    digests.clear(); // clear the current preserved digest state
    Iterator it = _signers.iterator();
    while (it.hasNext()) {
        SignerInformation signer = (SignerInformation) it.next();
        digestAlgs.add(CMSUtils.fixAlgID(signer.getDigestAlgorithmID()));
        signerInfos.add(signer.toSignerInfo());
    }
    boolean isCounterSignature = (eContentType == null);
    ASN1ObjectIdentifier contentTypeOID = isCounterSignature ? CMSObjectIdentifiers.data
            : new ASN1ObjectIdentifier(eContentType);
    for (SignerInfo signerInfo : signerInfoList) {
        digestAlgs.add(signerInfo.getDigestAlgorithm());
        signerInfos.add(signerInfo);
    }
    ASN1Set certificates = null;
    if (!certs.isEmpty())
        certificates = CMSUtils.createBerSetFromList(certs);
    ASN1Set certrevlist = null;
    if (!crls.isEmpty())
        certrevlist = CMSUtils.createBerSetFromList(crls);
    ASN1OctetString octs = null;
    if (encapsulate && content != null) {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        content.write(bOut);
        octs = new BERConstructedOctetString(bOut.toByteArray());
    }
    ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
    SignedData sd = new SignedData(new DERSet(digestAlgs), encInfo, certificates, certrevlist,
            new DERSet(signerInfos));
    ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.signedData, sd);
    return new CMSSignedData(content, contentInfo);
}

From source file:org.xipki.pki.ca.server.impl.scep.Scep.java

License:Open Source License

private PkiMessage doServicePkiOperation(final CMSSignedData requestContent, final DecodedPkiMessage req,
        final String certProfileName, final String msgId, final AuditEvent event)
        throws MessageDecodingException, OperationException {
    ParamUtil.requireNonNull("requestContent", requestContent);
    ParamUtil.requireNonNull("req", req);

    String tid = req.getTransactionId().getId();
    // verify and decrypt the request
    audit(event, CaAuditConstants.NAME_tid, tid);
    if (req.getFailureMessage() != null) {
        audit(event, CaAuditConstants.NAME_SCEP_failureMessage, req.getFailureMessage());
    }/*from w ww  . j a v a 2 s  .  c o m*/
    Boolean bo = req.isSignatureValid();
    if (bo != null && !bo.booleanValue()) {
        audit(event, CaAuditConstants.NAME_SCEP_signature, "invalid");
    }
    bo = req.isDecryptionSuccessful();
    if (bo != null && !bo.booleanValue()) {
        audit(event, CaAuditConstants.NAME_SCEP_decryption, "failed");
    }

    PkiMessage rep = new PkiMessage(req.getTransactionId(), MessageType.CertRep, Nonce.randomNonce());
    rep.setRecipientNonce(req.getSenderNonce());

    if (req.getFailureMessage() != null) {
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badRequest);
    }

    bo = req.isSignatureValid();
    if (bo != null && !bo.booleanValue()) {
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badMessageCheck);
    }

    bo = req.isDecryptionSuccessful();
    if (bo != null && !bo.booleanValue()) {
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badRequest);
    }

    Date signingTime = req.getSigningTime();
    if (maxSigningTimeBiasInMs > 0) {
        boolean isTimeBad = false;
        if (signingTime == null) {
            isTimeBad = true;
        } else {
            long now = System.currentTimeMillis();
            long diff = now - signingTime.getTime();
            if (diff < 0) {
                diff = -1 * diff;
            }
            isTimeBad = diff > maxSigningTimeBiasInMs;
        }

        if (isTimeBad) {
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badTime);
        }
    } // end if

    // check the digest algorithm
    String oid = req.getDigestAlgorithm().getId();
    ScepHashAlgoType hashAlgoType = ScepHashAlgoType.forNameOrOid(oid);
    if (hashAlgoType == null) {
        LOG.warn("tid={}: unknown digest algorithm {}", tid, oid);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badAlg);
    } else {
        boolean supported = false;
        if (hashAlgoType == ScepHashAlgoType.SHA1) {
            if (caCaps.containsCapability(CaCapability.SHA1)) {
                supported = true;
            }
        } else if (hashAlgoType == ScepHashAlgoType.SHA256) {
            if (caCaps.containsCapability(CaCapability.SHA256)) {
                supported = true;
            }
        } else if (hashAlgoType == ScepHashAlgoType.SHA512) {
            if (caCaps.containsCapability(CaCapability.SHA512)) {
                supported = true;
            }
        }

        if (!supported) {
            LOG.warn("tid={}: unsupported digest algorithm {}", tid, oid);
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badAlg);
        }
    }

    // check the content encryption algorithm
    ASN1ObjectIdentifier encOid = req.getContentEncryptionAlgorithm();
    if (CMSAlgorithm.DES_EDE3_CBC.equals(encOid)) {
        if (!caCaps.containsCapability(CaCapability.DES3)) {
            LOG.warn("tid={}: encryption with DES3 algorithm is not permitted", tid, encOid);
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badAlg);
        }
    } else if (AES_ENC_ALGOS.contains(encOid)) {
        if (!caCaps.containsCapability(CaCapability.AES)) {
            LOG.warn("tid={}: encryption with AES algorithm {} is not permitted", tid, encOid);
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badAlg);
        }
    } else {
        LOG.warn("tid={}: encryption with algorithm {} is not permitted", tid, encOid);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badAlg);
    }

    if (rep.getPkiStatus() == PkiStatus.FAILURE) {
        return rep;
    }

    X509Ca ca;
    try {
        ca = caManager.getX509Ca(caName);
    } catch (CaMgmtException ex) {
        LogUtil.error(LOG, ex, tid + "=" + tid + ",could not get X509CA");
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, ex);
    }

    X500Name caX500Name = ca.getCaInfo().getCertificate().getSubjectAsX500Name();

    try {
        SignedData signedData;

        MessageType mt = req.getMessageType();
        audit(event, CaAuditConstants.NAME_SCEP_messageType, mt.toString());

        switch (mt) {
        case PKCSReq:
        case RenewalReq:
        case UpdateReq:
            CertificationRequest csr = CertificationRequest.getInstance(req.getMessageData());
            X500Name reqSubject = csr.getCertificationRequestInfo().getSubject();
            String reqSubjectText = X509Util.getRfc4519Name(reqSubject);
            LOG.info("tid={}, subject={}", tid, reqSubjectText);

            CmpControl cmpControl = caManager.getCmpControlObject(ca.getCaInfo().getCmpControlName());
            if (!caManager.getSecurityFactory().verifyPopo(csr, cmpControl.getPopoAlgoValidator())) {
                LOG.warn("tid={}, POPO verification failed", tid);
                throw FailInfoException.BAD_MESSAGE_CHECK;
            }

            CertificationRequestInfo csrReqInfo = csr.getCertificationRequestInfo();
            X509Certificate reqSignatureCert = req.getSignatureCert();
            boolean selfSigned = reqSignatureCert.getSubjectX500Principal()
                    .equals(reqSignatureCert.getIssuerX500Principal());

            String cn = X509Util.getCommonName(csrReqInfo.getSubject());
            if (cn == null) {
                throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE,
                        "tid=" + tid + ": no CommonName in requested subject");
            }

            String user = null;
            boolean authenticatedByPwd = false;

            String challengePwd = CaUtil.getChallengePassword(csrReqInfo);
            if (challengePwd != null) {
                String[] strs = challengePwd.split(":");
                if (strs != null && strs.length == 2) {
                    user = strs[0];
                    String password = strs[1];
                    authenticatedByPwd = ca.authenticateUser(user, password.getBytes());

                    if (!authenticatedByPwd) {
                        LOG.warn("tid={}: could not verify the challengePassword", tid);
                        throw FailInfoException.BAD_REQUEST;
                    }
                } else {
                    LOG.warn("tid={}: ignore challengePassword since it does not has the"
                            + " format <user>:<password>", tid);
                }
            } // end if

            if (selfSigned) {
                if (MessageType.PKCSReq != mt) {
                    LOG.warn("tid={}: self-signed certificate is not permitted for" + " messageType {}", tid,
                            mt);
                    throw FailInfoException.BAD_REQUEST;
                }
                if (user == null) {
                    LOG.warn("tid={}: could not extract user & password from challengePassword"
                            + ", which are required for self-signed signature certificate", tid);
                    throw FailInfoException.BAD_REQUEST;
                }
                checkCommonName(ca, user, cn);
            } else {
                if (user == null) {
                    // up to draft-nourse-scep-23 the client sends all messages to enroll
                    // certificate via MessageType PKCSReq
                    KnowCertResult knowCertRes = ca.knowsCertificate(reqSignatureCert);
                    if (!knowCertRes.isKnown()) {
                        LOG.warn("tid={}: signature certificate is not trusted by the CA", tid);
                        throw FailInfoException.BAD_REQUEST;
                    }
                    user = knowCertRes.getUser();
                } // end if

                // only the same subject is permitted
                String cnInSignatureCert = X509Util.getCommonName(
                        X500Name.getInstance(reqSignatureCert.getSubjectX500Principal().getEncoded()));
                boolean b2 = cn.equals(cnInSignatureCert);
                if (!b2) {
                    if (user != null) {
                        checkCommonName(ca, user, cn);
                    } else {
                        LOG.warn("tid={}: signature certificate is not trusted and {}", tid,
                                "no challengePassword is contained in the request");
                        throw FailInfoException.BAD_REQUEST;
                    }
                } // end if
            } // end if

            byte[] tidBytes = getTransactionIdBytes(tid);

            Extensions extensions = CaUtil.getExtensions(csrReqInfo);
            CertTemplateData certTemplateData = new CertTemplateData(csrReqInfo.getSubject(),
                    csrReqInfo.getSubjectPublicKeyInfo(), (Date) null, (Date) null, extensions,
                    certProfileName);
            X509CertificateInfo cert = ca.generateCertificate(certTemplateData, true, null, user,
                    RequestType.SCEP, tidBytes, msgId);
            /* Don't save SCEP message, since it contains password in plaintext
            if (ca.getCaInfo().isSaveRequest() && cert.getCert().getCertId() != null) {
            byte[] encodedRequest;
            try {
                encodedRequest = requestContent.getEncoded();
            } catch (IOException ex) {
                LOG.warn("could not encode request");
                encodedRequest = null;
            }
            if (encodedRequest != null) {
                long reqId = ca.addRequest(encodedRequest);
                ca.addRequestCert(reqId, cert.getCert().getCertId());
            }
            }*/

            signedData = buildSignedData(cert.getCert().getCert());
            break;
        case CertPoll:
            IssuerAndSubject is = IssuerAndSubject.getInstance(req.getMessageData());
            audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(is.getIssuer()));
            audit(event, CaAuditConstants.NAME_subject, X509Util.getRfc4519Name(is.getSubject()));

            ensureIssuedByThisCa(caX500Name, is.getIssuer());
            signedData = pollCert(ca, is.getSubject(), req.getTransactionId());
            break;
        case GetCert:
            IssuerAndSerialNumber isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
            BigInteger serial = isn.getSerialNumber().getPositiveValue();
            audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(isn.getName()));
            audit(event, CaAuditConstants.NAME_serial, LogUtil.formatCsn(serial));
            ensureIssuedByThisCa(caX500Name, isn.getName());
            signedData = getCert(ca, isn.getSerialNumber().getPositiveValue());
            break;
        case GetCRL:
            isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
            serial = isn.getSerialNumber().getPositiveValue();
            audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(isn.getName()));
            audit(event, CaAuditConstants.NAME_serial, LogUtil.formatCsn(serial));
            ensureIssuedByThisCa(caX500Name, isn.getName());
            signedData = getCrl(ca, serial);
            break;
        default:
            LOG.error("unknown SCEP messageType '{}'", req.getMessageType());
            throw FailInfoException.BAD_REQUEST;
        } // end switch

        ContentInfo ci = new ContentInfo(CMSObjectIdentifiers.signedData, signedData);
        rep.setMessageData(ci);
        rep.setPkiStatus(PkiStatus.SUCCESS);
    } catch (FailInfoException ex) {
        LogUtil.error(LOG, ex);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(ex.getFailInfo());
    }

    return rep;
}

From source file:org.xipki.pki.scep.message.DecodedNextCaMessage.java

License:Open Source License

@SuppressWarnings("unchecked")
public static DecodedNextCaMessage decode(final CMSSignedData pkiMessage,
        final CollectionStore<X509CertificateHolder> certStore) throws MessageDecodingException {
    ParamUtil.requireNonNull("pkiMessage", pkiMessage);

    SignerInformationStore signerStore = pkiMessage.getSignerInfos();
    Collection<SignerInformation> signerInfos = signerStore.getSigners();
    if (signerInfos.size() != 1) {
        throw new MessageDecodingException("number of signerInfos is not 1, but " + signerInfos.size());
    }/*from w w  w  .  j  ava2  s.  c om*/

    SignerInformation signerInfo = signerInfos.iterator().next();

    SignerId sid = signerInfo.getSID();

    Collection<?> signedDataCerts = null;
    if (certStore != null) {
        signedDataCerts = certStore.getMatches(sid);
    }

    if (signedDataCerts == null || signedDataCerts.isEmpty()) {
        signedDataCerts = pkiMessage.getCertificates().getMatches(signerInfo.getSID());
    }

    if (signedDataCerts == null || signedDataCerts.size() != 1) {
        throw new MessageDecodingException("could not find embedded certificate to verify the signature");
    }

    AttributeTable signedAttrs = signerInfo.getSignedAttributes();
    if (signedAttrs == null) {
        throw new MessageDecodingException("missing signed attributes");
    }

    Date signingTime = null;
    // signingTime
    ASN1Encodable attrValue = ScepUtil.getFirstAttrValue(signedAttrs, CMSAttributes.signingTime);
    if (attrValue != null) {
        signingTime = Time.getInstance(attrValue).getDate();
    }

    DecodedNextCaMessage ret = new DecodedNextCaMessage();
    if (signingTime != null) {
        ret.setSigningTime(signingTime);
    }

    ASN1ObjectIdentifier digestAlgOid = signerInfo.getDigestAlgorithmID().getAlgorithm();
    ret.setDigestAlgorithm(digestAlgOid);

    String sigAlgOid = signerInfo.getEncryptionAlgOID();
    if (!PKCSObjectIdentifiers.rsaEncryption.getId().equals(sigAlgOid)) {
        ASN1ObjectIdentifier tmpDigestAlgOid;
        try {
            tmpDigestAlgOid = ScepUtil.extractDigesetAlgorithmIdentifier(signerInfo.getEncryptionAlgOID(),
                    signerInfo.getEncryptionAlgParams());
        } catch (Exception ex) {
            final String msg = "could not extract digest algorithm from signerInfo.signatureAlgorithm: "
                    + ex.getMessage();
            LOG.error(msg);
            LOG.debug(msg, ex);
            ret.setFailureMessage(msg);
            return ret;
        }
        if (!digestAlgOid.equals(tmpDigestAlgOid)) {
            ret.setFailureMessage(
                    "digestAlgorithm and encryptionAlgorithm do not use" + " the same digestAlgorithm");
            return ret;
        }
    } // end if

    X509CertificateHolder tmpSignerCert = (X509CertificateHolder) signedDataCerts.iterator().next();
    X509Certificate signerCert;
    try {
        signerCert = ScepUtil.toX509Cert(tmpSignerCert.toASN1Structure());
    } catch (CertificateException ex) {
        final String msg = "could not construct X509CertificateObject: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }
    ret.setSignatureCert(signerCert);

    // validate the signature
    SignerInformationVerifier verifier;
    try {
        verifier = new JcaSimpleSignerInfoVerifierBuilder().build(signerCert.getPublicKey());
    } catch (OperatorCreationException ex) {
        final String msg = "could not build signature verifier: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }

    boolean signatureValid;
    try {
        signatureValid = signerInfo.verify(verifier);
    } catch (CMSException ex) {
        final String msg = "could not verify the signature: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }

    ret.setSignatureValid(signatureValid);
    if (!signatureValid) {
        return ret;
    }

    // MessageData
    CMSTypedData signedContent = pkiMessage.getSignedContent();
    ASN1ObjectIdentifier signedContentType = signedContent.getContentType();
    if (!CMSObjectIdentifiers.signedData.equals(signedContentType)) {
        // fall back: some SCEP client use id-data
        if (!CMSObjectIdentifiers.data.equals(signedContentType)) {
            ret.setFailureMessage(
                    "either id-signedData or id-data is excepted, but not '" + signedContentType.getId());
            return ret;
        }
    }

    ContentInfo contentInfo = ContentInfo.getInstance((byte[]) signedContent.getContent());
    SignedData signedData = SignedData.getInstance(contentInfo.getContent());

    List<X509Certificate> certs;
    try {
        certs = ScepUtil.getCertsFromSignedData(signedData);
    } catch (CertificateException ex) {
        final String msg = "could not extract Certificates from the message: " + ex.getMessage();
        LOG.error(msg);
        LOG.debug(msg, ex);
        ret.setFailureMessage(msg);
        return ret;
    }

    final int n = certs.size();

    X509Certificate caCert = null;
    List<X509Certificate> raCerts = new LinkedList<X509Certificate>();
    for (int i = 0; i < n; i++) {
        X509Certificate cert = certs.get(i);
        if (cert.getBasicConstraints() > -1) {
            if (caCert != null) {
                final String msg = "multiple CA certificates is returned, but exactly 1 is expected";
                LOG.error(msg);
                ret.setFailureMessage(msg);
                return ret;
            }
            caCert = cert;
        } else {
            raCerts.add(cert);
        }
    } // end for

    if (caCert == null) {
        final String msg = "no CA certificate is returned";
        LOG.error(msg);
        ret.setFailureMessage(msg);
        return ret;
    }

    X509Certificate[] locaRaCerts;
    if (raCerts.isEmpty()) {
        locaRaCerts = null;
    } else {
        locaRaCerts = raCerts.toArray(new X509Certificate[0]);
    }

    AuthorityCertStore authorityCertStore = AuthorityCertStore.getInstance(caCert, locaRaCerts);
    ret.setAuthorityCertStore(authorityCertStore);

    return ret;
}

From source file:org.xipki.pki.scep.message.NextCaMessage.java

License:Open Source License

public ContentInfo encode(final PrivateKey signingKey, final X509Certificate signerCert,
        final X509Certificate[] cmsCertSet) throws MessageEncodingException {
    ParamUtil.requireNonNull("signingKey", signingKey);
    ParamUtil.requireNonNull("signerCert", signerCert);

    try {//from   w  w w .  j  ava  2  s.  co m
        byte[] degenratedSignedDataBytes;
        try {
            CMSSignedDataGenerator degenerateSignedData = new CMSSignedDataGenerator();
            degenerateSignedData.addCertificate(new X509CertificateHolder(caCert.getEncoded()));
            if (raCerts != null && !raCerts.isEmpty()) {
                for (X509Certificate m : raCerts) {
                    degenerateSignedData.addCertificate(new X509CertificateHolder(m.getEncoded()));
                }
            }

            degenratedSignedDataBytes = degenerateSignedData.generate(new CMSAbsentContent()).getEncoded();
        } catch (CertificateEncodingException ex) {
            throw new MessageEncodingException(ex.getMessage(), ex);
        }

        CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

        // I don't known which hash algorithm is supported by the client, use SHA-1
        String signatureAlgo = getSignatureAlgorithm(signingKey, ScepHashAlgoType.SHA1);
        ContentSigner signer = new JcaContentSignerBuilder(signatureAlgo).build(signingKey);

        // signerInfo
        JcaSignerInfoGeneratorBuilder signerInfoBuilder = new JcaSignerInfoGeneratorBuilder(
                new BcDigestCalculatorProvider());

        signerInfoBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator());

        SignerInfoGenerator signerInfo = signerInfoBuilder.build(signer, signerCert);
        generator.addSignerInfoGenerator(signerInfo);

        CMSTypedData cmsContent = new CMSProcessableByteArray(CMSObjectIdentifiers.signedData,
                degenratedSignedDataBytes);

        // certificateSet
        ScepUtil.addCmsCertSet(generator, cmsCertSet);
        return generator.generate(cmsContent, true).toASN1Structure();
    } catch (CMSException ex) {
        throw new MessageEncodingException(ex);
    } catch (CertificateEncodingException ex) {
        throw new MessageEncodingException(ex);
    } catch (IOException ex) {
        throw new MessageEncodingException(ex);
    } catch (OperatorCreationException ex) {
        throw new MessageEncodingException(ex);
    }
}