bouncycastle mail api实现加密和签名邮件

bouncycastle mail api 实现加密和签名邮件

1,  下载 bouncycastle bcmail 版本,注意:一定要和 bcprovider 的版本号一致。

2,  下载 webeasymail 作为自己在 xp 下的一个 mail 服务器,这样比较方便程序测试,因为下载除了 gmail 以为其他 mail 服务器的免费服务都不支持 smtp 服务了。

3,  熟悉 javamail 的使用方法,熟悉 bc keystore api 等。

 

实现了简单的发送和接受加密和签名邮件的小程序,发送邮件 SendMail ,接受邮件的 ReceiveMail ,仅供参考,里面几个 load 需要相应的 keystore 的支持。

1,SendMail:

import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.security.cert.CertStore; import java.security.cert.Certificate; import java.security.cert.CollectionCertStoreParameters; import javax.security.auth.x500.X500PrivateCredential; import java.util.Arrays; import java.util.Iterator; import java.util.Collections; import java.util.Properties; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.InternetAddress; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.Address; import javax.mail.Authenticator; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute; import org.bouncycastle.asn1.smime.SMIMECapability; import org.bouncycastle.asn1.smime.SMIMECapabilityVector; import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute; import org.bouncycastle.mail.smime.SMIMESigned; import org.bouncycastle.mail.smime.SMIMESignedGenerator; import org.bouncycastle.mail.smime.SMIMEUtil; import org.bouncycastle.mail.smime.SMIMEEnveloped; import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator; public class SendMail{ public static void main(String args[]){ try{ KeyStore credentials = KeyStore.getInstance("JKS"); credentials.load(new FileInputStream("kgn163.jks"),"kgn123".toCharArray()); PrivateKey key = (PrivateKey)credentials.getKey("kgn","kgn123".toCharArray()); Certificate[] chain = credentials.getCertificateChain("kgn"); CertStore certsAndCRLs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(chain)), "BC"); X509Certificate cert = (X509Certificate)chain[0]; sendEnvelopedMail(cert); sendSignedMail(cert,key,certsAndCRLs); }catch (Exception e){ e.printStackTrace(System.out); } } public static Session getSendMailSession(){ try{ Properties props = System.getProperties(); props.put("mail.smtp.host", "127.0.0.1"); props.put("mail.smtp.auth", "true"); Authenticator myauth = new MyAuthenticator("[email protected]","123456"); Session session = Session.getDefaultInstance(props, myauth); return session; }catch (Exception e){ e.printStackTrace(System.out); return null; } } public static void sendEnvelopedMail(X509Certificate cert){ try{ MimeBodyPart dataPart = new MimeBodyPart(); dataPart.setText("Hello world!"); SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator(); gen.addKeyTransRecipient(cert); MimeBodyPart envPart = gen.generate(dataPart, SMIMEEnvelopedGenerator.DES_EDE3_CBC, "BC"); Session session = getSendMailSession(); MimeMessage mail = createMimeMessage("example enveloped message", envPart.getContent(), envPart.getContentType(),session); Transport.send(mail); }catch (Exception e){ e.printStackTrace(System.out); } } public static void sendSignedMail(X509Certificate cert,PrivateKey key,CertStore certsAndCRLs){ try{ MimeBodyPart dataPart = new MimeBodyPart(); dataPart.setText("Hello world!"); MimeMultipart multiPart = createMultipartWithSignature(key, cert, certsAndCRLs, dataPart); Session session = getSendMailSession(); MimeMessage mail = createMimeMessage("example signed message", multiPart, multiPart.getContentType(),session); Transport.send(mail); }catch (Exception e){ e.printStackTrace(System.out); } } public static MimeMessage createMimeMessage(String subject, Object content, String contentType,Session session){ try{ Address fromUser = new InternetAddress("[email protected]"); Address toUser = new InternetAddress("[email protected]"); MimeMessage message = new MimeMessage(session); message.setFrom(fromUser); message.setRecipient(Message.RecipientType.TO, toUser); message.setSubject(subject); message.setContent(content, contentType); message.saveChanges(); return message; }catch(Exception e){ e.printStackTrace(System.out); return null; } } public static MimeMultipart createMultipartWithSignature(PrivateKey key, X509Certificate cert, CertStore certsAndCRLs, MimeBodyPart dataPart){ try{ ASN1EncodableVector signedAttrs = new ASN1EncodableVector(); SMIMECapabilityVector caps = new SMIMECapabilityVector(); caps.addCapability(SMIMECapability.aES256_CBC); caps.addCapability(SMIMECapability.dES_EDE3_CBC); caps.addCapability(SMIMECapability.rC2_CBC, 128); signedAttrs.add(new SMIMECapabilitiesAttribute(caps)); signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute( SMIMEUtil.createIssuerAndSerialNumberFor(cert))); SMIMESignedGenerator gen = new SMIMESignedGenerator(); gen.addSigner(key, cert, SMIMESignedGenerator.DIGEST_SHA1, new AttributeTable(signedAttrs), null); gen.addCertificatesAndCRLs(certsAndCRLs); return gen.generate(dataPart, "BC"); }catch (Exception e){ e.printStackTrace(System.out); return null; } } }

2,ReceiveMail:

import java.io.FileInputStream; import java.io.ByteArrayInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.security.cert.PKIXBuilderParameters; import java.security.cert.PKIXCertPathBuilderResult; import java.security.cert.CertPathBuilder; import java.security.cert.CertStore; import java.security.cert.X509CertSelector; import java.security.cert.Certificate; import java.security.cert.TrustAnchor; import java.security.cert.CollectionCertStoreParameters; import java.util.Collections; import java.util.Properties; import java.util.Iterator; import java.util.Properties; import java.util.Arrays; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.InternetAddress; import javax.mail.Multipart; import javax.mail.Part; import javax.mail.Message; import javax.mail.Session; import javax.mail.Address; import javax.mail.Folder; import javax.mail.Store; import javax.mail.Flags; import org.bouncycastle.mail.smime.SMIMESigned; import org.bouncycastle.mail.smime.SMIMEUtil; import org.bouncycastle.mail.smime.SMIMEEnveloped; import org.bouncycastle.cms.RecipientId; import org.bouncycastle.cms.RecipientInformationStore; import org.bouncycastle.cms.RecipientInformation; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.SignerInformationStore; public class ReceiveMail{ public static void main(String args[]){ try{ KeyStore credentials = KeyStore.getInstance("JKS"); credentials.load(new FileInputStream("kgn163.jks"),"kgn123".toCharArray()); PrivateKey key = (PrivateKey)credentials.getKey("kgn","kgn123".toCharArray()); Certificate[] chain = credentials.getCertificateChain("kgn"); CertStore certsAndCRLs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(chain)), "BC"); X509Certificate cert = (X509Certificate)chain[0]; X509Certificate rootCert = (X509Certificate)credentials.getCertificate("root"); Folder folder = getFolder("INBOX"); Message message[] = folder.getMessages(); for(int i=0;i<message.length;i++){ System.out.println("the "+(i+1)+" mail" +"------------------------------------------------"); MimeMessage mail = (MimeMessage)message[i]; String out_from = ((InternetAddress)message[i].getFrom()[0]).getAddress(); System.out.println("From:"+out_from); System.out.println("Subject:"+message[i].getSubject()); if (mail.isMimeType("multipart/signed")){ System.out.println("a signed mail"); receiveSignedMail(mail,rootCert); }else if(mail.isMimeType("application/pkcs7-mime")||mail.isMimeType("application/x-pkcs7-mime")){ System.out.println("a enveloped mail"); receiveEnveloped(mail,key,cert); }else { System.out.println("not a identified mail"); } message[i].setFlag(Flags.Flag.DELETED,true); } folder.close(true); }catch(Exception e){ e.printStackTrace(System.out); } } public static void receiveEnveloped(Message mail,PrivateKey key, X509Certificate cert){ try{ SMIMEEnveloped enveloped = new SMIMEEnveloped((MimeMessage)mail); RecipientId recId = new RecipientId(); recId.setSerialNumber(cert.getSerialNumber()); recId.setIssuer(cert.getIssuerX500Principal().getEncoded()); RecipientInformationStore recipients = enveloped.getRecipientInfos(); RecipientInformation recipient = recipients.get(recId); if (recipient != null){ MimeBodyPart recoveredPart = SMIMEUtil.toMimeBodyPart(recipient.getContent(key, "BC")); System.out.print("Content: "); System.out.println(recoveredPart.getContentType()); if(recoveredPart.isMimeType("multipart/alternative")){ Multipart mp = (Multipart) recoveredPart.getContent(); int index = 0; if (mp.getCount() > 1) index = 1; Part tmp = mp.getBodyPart(index); System.out.println(tmp.getContent()); }else { System.out.println(recoveredPart.getContent()); } }else{ System.out.println("decrypt error"); } }catch(Exception e){ e.printStackTrace(System.out); } } public static void receiveSignedMail(Message mail,X509Certificate rootCert){ try{ SMIMESigned signed = new SMIMESigned((MimeMultipart)mail.getContent()); if (isValid(signed, rootCert)){ System.out.println("verification succeeded"); }else{ System.out.println("verification failed"); } MimeBodyPart content = signed.getContent(); System.out.print("Content: "); System.out.println(content.getContent()); }catch(Exception e){ e.printStackTrace(System.out); } } public static Folder getFolder(String folderName){ try{ Properties props = System.getProperties(); props.put("mail.smtp.host", "127.0.0.1"); Session session = Session.getDefaultInstance(props,null); Store store = session.getStore("pop3"); store.connect("127.0.0.1","[email protected]","123456"); Folder folder = store.getFolder(folderName); folder.open(Folder.READ_WRITE); return folder; }catch(Exception e){ e.printStackTrace(System.out); return null; } } public static PKIXCertPathBuilderResult buildPath(X509Certificate rootCert, X509CertSelector endConstraints, CertStore certsAndCRLs){ try{ CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC"); PKIXBuilderParameters buildParams = new PKIXBuilderParameters(Collections.singleton(new TrustAnchor(rootCert, null)), endConstraints); buildParams.addCertStore(certsAndCRLs); buildParams.setRevocationEnabled(false); return (PKIXCertPathBuilderResult)builder.build(buildParams); }catch (Exception e){ e.printStackTrace(System.out); return null; } } static boolean[] getKeyUsageForSignature(){ boolean[] val = new boolean[9]; val[0] = true; //Digital Signature. val[1] = false; //Non Repudiation. val[2] = true; //Key Encipherment. val[3] = true; //Data Encipherment. val[4] = false; //Key Agreement. val[5] = false; //Certificate Sign. val[6] = false; //CRL Sign. val[7] = false; //Encipher Only. val[8] = false; //Decipher Only. return val; } public static boolean isValid(CMSSignedData signedData,X509Certificate rootCert){ try{ CertStore certsAndCRLs = signedData.getCertificatesAndCRLs("Collection", "BC"); SignerInformationStore signers = signedData.getSignerInfos(); Iterator it = signers.getSigners().iterator(); if (it.hasNext()){ SignerInformation signer = (SignerInformation)it.next(); X509CertSelector signerConstraints = signer.getSID(); signerConstraints.setKeyUsage(getKeyUsageForSignature()); System.out.println("Signed by "+signerConstraints.getIssuer()); PKIXCertPathBuilderResult result = buildPath(rootCert, signerConstraints, certsAndCRLs); return signer.verify(result.getPublicKey(), "BC"); } return false; }catch (Exception e){ e.printStackTrace(System.out); return false; } } }

 

你可能感兴趣的:(exception,加密,session,api,null,credentials)