simple-java-mail / java-utils-mail-smime

11 stars 5 forks source link

Received email giving "Your digital ID name cannot be found by the underlying security system" - Signing and encryption #11

Closed shivanshnema closed 6 months ago

shivanshnema commented 6 months ago

I am trying to send the smime signed and encrypted mail using my email IDs. I got two smime certificates each for my two Gmail IDs. I tried to use the SMIMETestUtil class for testing the scenario. I am successfully able to send mail from one email to another. But when I am trying to open it, I receive the error "Your digital ID name cannot be found by the underlying security system".

I am using the below code.

package org.simplejavamail.utils.mail.smime;

import jakarta.mail.Authenticator;
import jakarta.mail.MessagingException;
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Properties;

import static jakarta.mail.Transport.send;
import static org.assertj.core.api.Assertions.assertThat;

public class SmimeUtilTest {

    private static final String SignatureAlgorithmRsaPss = "SHA256WITHRSAANDMGF1";
    private SmimeKeyStore alicesKeyStore;
    private SmimeKeyStore bobsKeyStore;
    private Session mailSession;

    @Before
    public void setup() throws MessagingException, KeyStoreException, NoSuchProviderException, CertificateException, IOException, NoSuchAlgorithmException {
        Security.addProvider(new BouncyCastleProvider());
        InputStream alicesKeystoreStream = this.getClass().getClassLoader().getResourceAsStream("sh_cert.pfx");
        this.alicesKeyStore = new SmimeKeyStore(alicesKeystoreStream, "<mypass>".toCharArray());
        System.out.println(this.alicesKeyStore.getPrivateKeyAliases());
        InputStream bobsKeystoreStream = this.getClass().getClassLoader().getResourceAsStream("sho_cert.pfx");
        this.bobsKeyStore = new SmimeKeyStore(bobsKeystoreStream, "<mypass>".toCharArray());

        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class",
                "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        //get Session

        this.mailSession = Session.getDefaultInstance(props,
                new Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication("<my id>","<my pass>");
                    }
                });
    }

    private MimeMessage createTestMessage(String from, String to) throws MessagingException {
        MimeMessage testMessage = new MimeMessage(this.mailSession);
        testMessage.setFrom(new InternetAddress(from));
        testMessage.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(to));
        testMessage.setSubject("This is a test email");
        testMessage.setContent("This is some test content for the test email's body", "text/plain; charset=utf-8");
        return testMessage;
    }

    @Test
    public void SuccessfullySignAndValidate() throws MessagingException, IOException {
        MimeMessage testMessage = createTestMessage("alice@testcorp.com", "alice@testcorp.com");
        SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
        MimeMessage signedMessage = SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey);
        MimeMultipart multipartContent = (MimeMultipart) signedMessage.getContent();
        assertThat(SmimeUtil.getStatus(multipartContent)).isEqualTo(SmimeState.SIGNED);
        assertThat(SmimeUtil.checkSignature(multipartContent)).isTrue();
    }

    @Test
    public void SuccessfullyEnvelopeAndDecryptDefault() throws MessagingException {
        MimeMessage testMessage = createTestMessage("<from-id>", "<to-id>");
        SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("<my alias>", "<my pass>".toCharArray());
        X509Certificate alicesCert = alicesKey.getCertificate();
        MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession, null,
                SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey),
                alicesCert);

        send(encryptedMessage);

        assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
        MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, alicesKey);
        assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
    }

    @Test
    public void SuccessfullyEnvelopeAndDecrypt() throws MessagingException {
        MimeMessage testMessage = createTestMessage("alice@testcorp.com", "alice@testcorp.com");
        SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
        X509Certificate alicesCert = alicesKey.getCertificate();
        MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession,
                SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey, SignatureAlgorithmRsaPss),
                null, alicesCert, KeyEncapsulationAlgorithm.RSA_OAEP_SHA256, CMSAlgorithm.AES256_CBC);
        assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
        MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, alicesKey);
        assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
    }

    @Test
    public void AliceToBoEnvelopeAndDecrypt() throws MessagingException {
        MimeMessage testMessage = createTestMessage("<from-id>", "<to-id>");
        SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("<my alias>", "<my pass>".toCharArray());
        SmimeKey bobsKey = this.bobsKeyStore.getPrivateKey("<my alias>", "<my pass>".toCharArray());
        X509Certificate bobsCert = bobsKey.getCertificate();
        System.out.println(Arrays.toString(bobsCert.getKeyUsage()));
        MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession,
                SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey, SignatureAlgorithmRsaPss),
                null, bobsCert, KeyEncapsulationAlgorithm.RSA_OAEP_SHA512, CMSAlgorithm.AES256_GCM);

         send(encryptedMessage);
    }

    @Test
    public void BobToAliceEnvelopeAndDecrypt() throws MessagingException {
        MimeMessage testMessage = createTestMessage("bob@testcorp.com", "alice@testcorp.com");
        SmimeKey bobsKey = this.bobsKeyStore.getPrivateKey("bob", "bob".toCharArray());
        SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
        X509Certificate alicesCert = alicesKey.getCertificate();
        MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession,
                SmimeUtil.sign(this.mailSession, null, testMessage, bobsKey, SignatureAlgorithmRsaPss),
                null, alicesCert, KeyEncapsulationAlgorithm.RSA_OAEP_SHA384, CMSAlgorithm.AES192_CCM);
        assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
        MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, alicesKey);
        assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
    }
}

image

bbottema commented 6 months ago

Do these tests run successfully? When do you get the popup from Outlook? I'm not actually a S/MIME expert, not even on this library, but it looks to me as if you haven't configured your certificates on Outlook/Windows system. It's an odd message for that, though. So I'm kinda clueless here.