Generate CMS with already encrypted content

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Generate CMS with already encrypted content




During the recovery workflow of an escrowed private key, I have :

-                      A private key, encrypted with an AES session key, ;

-                      This AES session key, encrypted with a provided external X.509 certificate


When I try to get, by hands, the clear private key, it works:

1-                  Decryption of the session key with the corresponding private key

2-                  Decryption of the private with the session key

So I am sure that the session key is a valid secret key and the private key a valid one too.


To send this recovered private key to its owner in a secure way, I want to build a CMS structure containing the encrypted session key and the encrypted private key. When I build such a CMS with the help of BC classes and clear private key, I can recover it by decrypting the CMS structure but that’s not what I want, because of the clear private key in memory:


X509Certificate externalCertX509 ;

CMSEnvelopedDataGenerator generator = new CMSEnvelopedDataGenerator();

generator.addRecipientInfoGenerator( new JceKeyTransRecipientInfoGenerator(externalCertX509).setProvider("BC") );

PrivateKey key;

CMSTypedData _content = new CMSProcessableByteArray(key.getEncoded());

CMSEnvelopedData _data = generator.generate(


                new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build() );

When I dive into BC classes, I can use them to build a CMS with clear private key, letting BC generate the symmetric session key. Unfortunately, I cannot make it work with both encrypted session and private keys:


ASN1EncodableVector recipientInfos = new ASN1EncodableVector();

AlgorithmIdentifier encAlgId;

ASN1OctetString encContent;

X509Certificate externalCertX509 ;

final IssuerAndSerialNumber issuerAndSerialNumber = new IssuerAndSerialNumber(

                new JcaX509CertificateHolder(x509EncryptionCert).toASN1Structure());

final RecipientIdentifier recipientIdentifier = new RecipientIdentifier(issuerAndSerialNumber);

final JceAsymmetricKeyWrapper wrapper = new JceAsymmetricKeyWrapper(x509EncryptionCert);

byte[] wrappedKey;


                new RecipientInfo(

                               new KeyTransRecipientInfo(



                                               new BEROctetString(wrappedKey)




final OutputEncryptor outputEncryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build();

encAlgId = outputEncryptor.getAlgorithmIdentifier();

encContent = new BEROctetString(encryptedKey);

EncryptedContentInfo eci = new EncryptedContentInfo(

new ASN1ObjectIdentifier(




ContentInfo contentInfo = new ContentInfo(


                new EnvelopedData(null, new DERSet(recipientInfos), eci, (ASN1Set) null));


CMSEnvelopedData _data = new CMSEnvelopedData(contentInfo);


I am able to decrypt the content of the CMS structure, but I cannot built a private key with it, it fails with the error " invalid key format":


final RecipientInformationStore recipientInformationStore = cmsEnvelopedData.getRecipientInfos();

KeyTransRecipientInformation keyTransRecipientInformation = (KeyTransRecipientInformation) recipientInformationStore.getRecipients().iterator().next();


JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(recipientPrivateKey);

byte[] decryptedData = keyTransRecipientInformation.getContent(recipient);

KeyFactory kf = KeyFactory.getInstance("RSA");

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decryptedData);

PrivateKey decryptedPrivateKey = kf.generatePrivate(keySpec);


Could someone help me to find what I'm doing wrong?

Thanks a lot for reading and taking time to answer