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

时间:2011-08-16 03:23:56

标签: java bouncycastle elliptic-curve smime

我正在尝试使用BouncyCastle的SMIME包来使用ECDSA X509证书创建加密邮件。根据BouncyCastle的发布说明,自1.32(我使用1.46)以来一直支持这一点,但我一直得到一个例外,说明没有找到ECDSA OID的密码。

  

org.bouncycastle.cms.CMSException:异常包装内容键:   无法创建密码:找不到任何支持的提供商   1.2.840.10045.2.1

以下是我正在使用的其中一个测试证书的片段

  Version: V3
  Subject: EMAILADDRESS=bob@example.com
  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));

我确信我做的事情显然是错的,但我现在没有看到它。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

正如托马斯·波尔丁所建议的那样(上文),需要使用ECDH来完成这项工作。因此,有必要使用JceKeyAgreeRecipientInfoGenerator而不是使用JceKeyTransRecipientInfoGenerator。

SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
JceKeyAgreeRecipientInfoGenerator rig = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA1KDF, senderPrivateKey, senderPublicKey, CMSAlgorithm.AES128_WRAP);
rig.setProvider("BC");
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 = "bob@example.com";

Address fromUser = new InternetAddress("alice@example.com");
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"));

答案 1 :(得分:1)

ECDSA是一种签名算法,而不是加密或密钥交换算法。为了加密消息,您需要收件人的RSA或Diffie-Hellman密钥(可能是ECDH)。