简体   繁体   中英

How to verify signature & decrypt a ; Encrypted & Signed content

I have a bouncy castle code that encrypts and sign a message(listed below) ; now I need to find the code for opposite end ; Verify the signature & decrypt the message. My search to find a solution for the past 2 days has been futile, as I could only find example for either verifying the signature (or) for decryption ; but not both. Please find below the encryption & signing code ; would greatly appreciate any hint or direction to Verify the signature & decrypt the message

Note : The method encryptAndSign() is called to encrypt and sign the Content/data

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.naming.NamingException;

import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;

public final class EncryptorNsigner {

     public byte[] encryptAndSign(final String content, final String selfSignedCert,
            final String encryptionCert) throws CertificateException, IOException,
            KeyStoreException, Exception {
        byte[] signedBytes;

        //Get key store
        KeyStore keyStore = this.getKeyStore();

        //Setup provider
        CMSSignedDataGenerator signatureGenerator = this.setUpProvider(
                keyStore, selfSignedCert);

        //Encrypt data
        byte[] encryptBytes = this.encryptData(content.getBytes("UTF-8"),
                getEncyptionCertFromKeystore(keyStore, encryptionCert), null);

        //Sign the encrypted data
        signedBytes = this.signPkcs7(encryptBytes, signatureGenerator);

        return Base64.encode(signedBytes);
    }


    private KeyStore getKeyStore() throws NamingException, KeyStoreException, 
                        FileNotFoundException, CertificateException, IOException,
                        NoSuchAlgorithmException{

        ...
        return keystore;
    }

    private X509Certificate getEncyptionCertFromKeystore(final KeyStore keystore, final String encryptionCertName) 
            throws CertificateException, IOException, KeyStoreException{

        Certificate c = keystore.getCertificate(encryptionCertName);

        X509CertificateHolder certHolder = new X509CertificateHolder(c.getEncoded());

        return new JcaX509CertificateConverter().setProvider( "BC" )
                  .getCertificate(certHolder );
    }

    private CMSSignedDataGenerator setUpProvider(final KeyStore keystore, String signCertName) throws Exception {

        Security.addProvider(new BouncyCastleProvider());

        //Get certificate chain
        Certificate[] certchain = (Certificate[]) keystore.getCertificateChain(signCertName);


        final List<Certificate> certlist = new ArrayList<Certificate>();

        //Add the certificates in Certificate chain to the Certificate list
        for (int i = 0, length = certchain == null ? 0 : certchain.length; i < length; i++) {
            certlist.add(certchain[i]);
        }

        //Class for storing certificates for later lookup
        Store certstore = new JcaCertStore(certlist);

        //Get certificate
        Certificate cert = keystore.getCertificate(signCertName);

        String algorithm = "SHA1withRSA";
        String keyStorePwd = "....";

        ContentSigner signer = new JcaContentSignerBuilder(algorithm).setProvider("BC").
                build((PrivateKey) (keystore.getKey(signCertName, keyStorePwd.toCharArray())));

        CMSSignedDataGenerator generator = new CMSSignedDataGenerator();


        generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").
                build()).build(signer, (X509Certificate) cert));

        generator.addCertificates(certstore);

        return generator;
    }


    private byte[] signPkcs7(final byte[] content, final CMSSignedDataGenerator generator) 
            throws CMSException, IOException {

        CMSTypedData cmsdata = new CMSProcessableByteArray(content);
        CMSSignedData signeddata = generator.generate(cmsdata, true);
        return signeddata.getEncoded();
    }

     private byte[] encryptData(byte[] dataToEncrypt, X509Certificate recipientCert, String algorithmName) throws IOException{

        CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();                                    

        CMSEnvelopedData ed;
        AlgorithmIdentifier digestAlgorithm;
        if (algorithmName!=null && !algorithmName.isEmpty()){
             digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find(new DefaultSignatureAlgorithmIdentifierFinder().find(algorithmName));


            try {

                edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(recipientCert).setProvider("BC"));
                ed = edGen.generate(new CMSProcessableByteArray(dataToEncrypt),
                                                new JceCMSContentEncryptorBuilder(digestAlgorithm.getAlgorithm())
                                                       .setProvider("BC").build());
            } catch (Exception e) {
                throw new IOException(e.getMessage());        
            }

        }
        else{
            try {

                edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(recipientCert).setProvider("BC"));
                ed = edGen.generate(new CMSProcessableByteArray(dataToEncrypt),
                                                new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC) //Default algorithmName = DES_EDE3_CBC
                                                       .setProvider("BC").build());
            } catch (Exception e) {
                throw new IOException(e.getMessage());        
            }
        }    

        return ed.getEncoded();         
    }

    }

2 years waiting for an answer. I hope you find the solution. To help others, here is a sample for reading SMIME emails and decrypt attachments. It's based on the fact that the sender used your public key to encrypt and you got your key and password to decrypt the message.

Security.addProvider(new BouncyCastleProvider());

                    // IMAP encrypt 
                    final KeyStore ks = KeyStore.getInstance("PKCS12");
                    final String password = CERTIFICAT_SMIME_PWD;
                    ks.load(this.class.getClassLoader()
                            .getResourceAsStream(CERTIFICAT_SMIME_PFX), password.toCharArray());
                    final String alias = ks.aliases().nextElement();

                    final PrivateKey pKey = (PrivateKey) ks.getKey(alias, password.toCharArray());

                    final SMIMEEnveloped m = new SMIMEEnveloped((MimeMessage) message);
                    final RecipientInformationStore recipients = m.getRecipientInfos();

                    final X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
                    final RecipientId recId = new JceKeyTransRecipientId(cert);
                    final RecipientInformation recipient = recipients.get(recId);
                    final byte[] content = recipient.getContent(new JceKeyTransEnvelopedRecipient(pKey)
                            .setProvider(BouncyCastleProvider.PROVIDER_NAME));

                    final String providerName = BouncyCastleProvider.PROVIDER_NAME;
                    final MimeBodyPart res = SMIMEUtil.toMimeBodyPart(content);

                    final MimeMultipart parts = (MimeMultipart) res.getContent();

                    for (int i = 0; i < parts.getCount(); i++) {
                        final BodyPart part = parts.getBodyPart(i);
                        if (part.getContent() instanceof Multipart) {
                            multipart = (Multipart) part.getContent();
                        }
                    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM