Skip to content

Support AuthEnvelopedData in mail SMIME - #1791

Closed
bukka wants to merge 1 commit into
bcgit:mainfrom
bukka:mail-smime-auth-enveloped
Closed

Support AuthEnvelopedData in mail SMIME#1791
bukka wants to merge 1 commit into
bcgit:mainfrom
bukka:mail-smime-auth-enveloped

Conversation

@bukka

@bukka bukka commented Aug 28, 2024

Copy link
Copy Markdown
Contributor

This adds SMIMEAuthEnveloped classes that work in a similar way as SMIMEEnveloped but are meant for AuthEnvelopedData. That allows using AES GCM and improves S/MIME 4.0 support where this is required.

This adds SMIMEAuthEnveloped classes that work in a similar way as
SMIMEEnveloped but are meant for AuthEnvelopedData. That allows using
AES GCM and improves S/MIME 4.0 support where this is required.
@rde-infologic

rde-infologic commented Dec 18, 2024

Copy link
Copy Markdown

Hello,

Can someone in bc-java team can merge this ?

That's could be cool to add something like SMIMEEnvelopedUtil in order to crypt or decrypt with good container.

package org.bouncycastle.mail.smime;

import java.util.Arrays;
import java.util.List;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSAuthEnvelopedGenerator;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.mail.smime.SMIMEAuthEnveloped;
import org.bouncycastle.mail.smime.SMIMEAuthEnvelopedGenerator;
import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator;
import org.bouncycastle.mail.smime.SMIMEEnveloped;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeBodyPart;

public class SMIMEEnvelopedUtil
{
    public static RecipientInformationStore getRecipientInfos(MimeBodyPart message) throws MessagingException, CMSException
    {
        if(message.getContentType().equals(SMIMEAuthEnvelopedGenerator.AUTH_ENCRYPTED_CONTENT_TYPE))
        {
            return new SMIMEAuthEnveloped(message).getRecipientInfos();
        }
        return new SMIMEEnveloped(message).getRecipientInfos();
    }
    
    
    public static SMIMEEnvelopedGenerator getGenerator(ASN1ObjectIdentifier algorithm)
    {        
        List<String> authEnvelopedAlgo = Arrays.asList(
            CMSAuthEnvelopedGenerator.AES128_GCM, 
            CMSAuthEnvelopedGenerator.AES192_GCM, 
            CMSAuthEnvelopedGenerator.AES256_GCM);
        if(authEnvelopedAlgo.contains(algorithm.getId()))
        {
            return new SMIMEAuthEnvelopedGenerator();
        }
        return new SMIMEEnvelopedGenerator();
    }
}

for exemple :

/**
 * Encrypte le message
 */
public SMimeMessage crypter(X509Certificate cert) throws SMimeException
{
    try
    {
        try
        {
            if (cert == null)
            {
                throw new SMimeException(null, E.t("Certificat obligatoire pour l'encryption du message"));
            }

            setDefaults();

            /* Create the encrypter */
            SMIMEEnvelopedGenerator encrypter  = SMIMEEnvelopedUtil.getGenerator(getChiffrementAlgorithm());
            encrypter.setContentTransferEncoding(getContentTransferEncoding());
            encrypter.addRecipientInfoGenerator(
                new JceKeyTransRecipientInfoGenerator(cert).setProvider(SECURITY_PROVIDER));

            /* Encrypt the body part */
            MimeBodyPart encryptedPart = encrypter.generate(bodyPart,
                new JceCMSContentEncryptorBuilder(getChiffrementAlgorithm()).setProvider(SECURITY_PROVIDER).build());

            return new SMimeMessage(encryptedPart, this);
        }
        catch (org.bouncycastle.mail.smime.SMIMEException ex)
        {
            throw new SMimeException(null, E.t(ex.getMessage()), ex);
        }
    }
    catch (Exception e)
    {
        throw new SMimeException(null, E.t("Impossible d'encrypter le message"), e);
    }
}

/**
 * Décrypter le message
 */
public SMimeMessage decrypter(PrivateKey privateKey) throws SMimeException
{
    if (privateKey == null)
    {
        throw new SMimeException(null, E.t("Clé privé obligatoire pour décrypter le message"));
    }

    try
    {
        setDefaults();

        RecipientId recId = new JceKeyTransRecipientId(cert);

        RecipientInformationStore recipientsInfo = SMIMEEnvelopedUtil.getRecipientInfos(bodyPart);
        RecipientInformation recipientInfo = recipientsInfo.get(recId);

        if (recipientInfo == null)
        {
            throw new SMimeException(null, E.t("Contenu encrypté invalide"));
        }

        JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(privateKey).setProvider(SECURITY_PROVIDER);

        ByteArrayInputStream ins = new ByteArrayInputStream(recipientInfo.getContent(recipient));
        MimeBodyPart decryptedPart = new MimeBodyPart(ins);
        return new SMimeMessage(decryptedPart, this);
    }
    catch (Exception e)
    {
        throw new SMimeException(null, E.t("Impossible de décrypter le message"), e);
    }
}

@dghgit dghgit self-assigned this Dec 31, 2024
@dghgit

dghgit commented Dec 31, 2024

Copy link
Copy Markdown
Contributor

Thanks for the PR. This is now merged with minor changes and also available on https://www.bouncycastle.org/betas

@dghgit dghgit closed this Dec 31, 2024
hubot pushed a commit that referenced this pull request Dec 31, 2024
@bukka

bukka commented Dec 31, 2024

Copy link
Copy Markdown
Contributor Author

Thanks @dghgit ! I will remember to update the code style in my IDE for the future contributions. Isn't there by any chance any code style scheme available? I use IntelliJ so it can use either IntelliJ IDEA code style XML or Eclipse XML Profile format. Alternatively I will just update it to match your changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants