2011-08-16 4 views
2

BouncyCastle의 SMIME 패키지를 사용하여 ECDSA X509 인증서를 사용하여 암호화 된 메시지를 만들려고합니다. BouncyCastle의 릴리스 노트에 따르면, 1.32 (1.46 사용)부터 지원되었지만 ECDSA OID에 대한 암호가 발견되지 않는다는 예외가 계속 발생합니다.EC X509 인증서를 사용하여 전자 메일을 암호화하는 중

org.bouncycastle.cms.CMSException : 예외 포장 콘텐츠 키 : 이 암호를 만들 수 없습니다 : 시험 중 하나에서 조각은 여기 1.2.840.10045.2.1

를 지원하는 모든 공급자를 찾을 수 없습니다입니다 내가 암호화 된 메시지를 만드는 데 사용하고

Version: V3 
    Subject: [email protected] 
    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

토마스 포르 닌 (Thomas Pornin)이 (위) 제안했듯이 ECDH를 사용해야이 작업을 수행 할 수있었습니다. 따라서 JceKeyTransRecipientInfoGenerator를 사용하는 대신 JceKeyAgreeRecipientInfoGenerator를 사용해야합니다.

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 = "[email protected]"; 

Address fromUser = new InternetAddress("[email protected]"); 
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

ECDSA는 서명 알고리즘이며 암호화 또는 키 교환 알고리즘이 아닙니다. 메시지를 암호화하려면 수신자의 RSA 또는 Diffie-Hellman 키 (ECDH 가능)가 필요합니다.

+0

EC 공개 키는 ECDSA와 ECDH 모두에 사용됩니까? 나는 서명 알고리즘에 SHA256withECDSA를 사용하면 would not 서명에 대한 키의 사용을 제한한다고 가정했다. 틀렸어? – senecaso

+1

ECDSA 키와 ECDH 키는 동일한 구조를 공유합니다. 그러나 대개 고유 한 라이프 사이클 및 스토리지 정책이 필요합니다 (예 : 대개의 경우 데이터 손실 시나리오를 피하기 위해 암호화 키의 백업 및/또는 에스크로를 유지하려는 경우가 있지만 서명 키용으로 사용하지 않으려는 경우) 개인 키 손상의 결과는 키 유형에 따라 상당히 다릅니다. 많은 X.509 인증서는 암호화에 서명 키를 사용하는 것을 금지하는 의도 된 사용법 (키 사용 확장)을 명시 적으로 지정합니다. –

+0

예, 이전 설명 [ECDSA 및 ECDH] 중 하나를 보았습니다 (http://stackoverflow.com/questions/4969570/is-there-a-difference-between-ecdh-and-ecdsa-keys). 필자는 인증서의 키 사용을 모든 항목 (별도의 이슈)으로 표시했다면 사용이 허용 될 것이라고 생각했습니다. 이 경우 BC에서 실패한 코드 섹션은 공개 키의 OID를 추출하고이를 Cipher.getInstance()에 전달하기 때문에 다른 부분이 진행되고 있다고 생각합니다. OID는 EC "키 유형"에 대한 것이므로 유효한 Cipher가 발견 될 것이라고는 기대하지 않습니다. – senecaso

관련 문제