java - 使用 EC X509 证书加密电子邮件

标签 java bouncycastle elliptic-curve smime

我正在尝试使用 BouncyCaSTLe 的 SMIME 包来使用 ECDSA X509 证书创建加密消息。根据 BouncyCaSTLe 的发行说明,从 1.32 开始就支持这一点(我使用的是 1.46),但我不断收到异常,指出找不到 ECDSA OID 的密码。

org.bouncycastle.cms.CMSException: exception wrapping content key: cannot create cipher: Cannot find any provider supporting 1.2.840.10045.2.1

这是我正在使用的测试证书之一的片段

  Version: V3
  Subject: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="53161e121a1f121717011600006e313c3113362b323e233f367d303c3e" rel="noreferrer noopener nofollow">[email protected]</a>
  Signature Algorithm: SHA256withECDSA, OID = 1.2.840.10045.4.3.2

  Key:  EC Public Key

我用来创建加密消息的代码如下所示:

// allow the use of the BC JCE
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
JceKeyTransRecipientInfoGenerator rig = new JceKeyTransRecipientInfoGenerator(cert);
gen.addRecipientInfoGenerator(rig);

MimeBodyPart msg = new MimeBodyPart();
msg.setText(message);

MimeBodyPart mp = gen.generate(
    msg,
    new JceCMSContentEncryptorBuilder(
        CMSAlgorithm.AES128_CBC).setProvider("BC").build());

Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);

// TODO: This is incorrect.  Perhaps AKA is better?
String to = cert.getSubjectDN().getName();

Address fromUser = new InternetAddress(from);
Address toUser = new InternetAddress(to);

MimeMessage body = new MimeMessage(session);
body.setFrom(fromUser);
body.setRecipient(Message.RecipientType.TO, toUser);
body.setSubject("example encrypted message");
body.setContent(mp.getContent(), mp.getContentType());
body.saveChanges();

body.writeTo(new FileOutputStream(filename));

我确信我正在做一些明显错误的事情,但我现在还没有看到它。有什么想法吗?

最佳答案

正如 Thomas Pornin 所建议的(上文),需要使用 ECDH 来完成这项工作。因此,有必要使用 JceKeyAgreeRecipientInfoGenerator,而不是使用 JceKeyTransRecipientInfoGenerator。

SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
JceKeyAgreeRecipientInfoGenerator rig = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA1KDF, senderPrivateKey, senderPublicKey, CMSAlgorithm.AES128_WRAP);
rig.setProvider(BouncyCastleProvider.PROVIDER_NAME);
rig.addRecipient(recipientX509Certificate);
gen.addRecipientInfoGenerator(rig);

MimeBodyPart msg = new MimeBodyPart();
msg.setText("This is a secret message");

MimeBodyPart mp = gen.generate(msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC").build());

Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);

String to = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7715181537120f161a071b125914181a" rel="noreferrer noopener nofollow">[email protected]</a>";

Address fromUser = new InternetAddress("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f89994919b9db89d80999588949dd69b9795" rel="noreferrer noopener nofollow">[email protected]</a>");
Address toUser = new InternetAddress(to);

MimeMessage body = new MimeMessage(session);
body.setFrom(fromUser);
body.setRecipient(Message.RecipientType.TO, toUser);
body.setSubject("example encrypted message");
body.setContent(mp.getContent(), mp.getContentType());
body.saveChanges();

body.writeTo(new FileOutputStream("/tmp/encrypted.msg"));

关于java - 使用 EC X509 证书加密电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7073319/

相关文章:

java - 如何从 native JPA INSERT 获取生成的标识值?

java - 如何创建 GWT 中检查的对象列表?

java - 如何从tomcat的context.xml中传递加密相关属性以用于java中的jdbc连接?

java - 使用给定私钥在椭圆曲线算法中生成公钥的代码

java - 使用此椭圆曲线点乘法计算的点不在曲线上,此类带来算术异常

java - 类扩展不止一个类Java?

java nashorn 访问父类(super class)成员

java - 使用 BouncyCaSTLe 签署 CSR

mysql - TimeStampToken 存储在 MySQL 还是 Oracle 中?

c# - .NET 中的 ECDiffieHellmanCng 是否具有实现 NIST SP 800-56A,第 5.8.1 节的 key 派生函数