我正在尝试使用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));
我确信我做的事情显然是错的,但我现在没有看到它。有什么想法吗?
答案 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)。