001: package org.bouncycastle.mail.smime.examples;
002:
003: import java.io.FileInputStream;
004: import java.io.ByteArrayOutputStream;
005: import java.io.ByteArrayInputStream;
006: import java.security.KeyStore;
007: import java.security.Security;
008: import java.security.PrivateKey;
009: import java.security.cert.Certificate;
010: import java.security.cert.X509Certificate;
011: import java.security.cert.CertStore;
012: import java.security.cert.CollectionCertStoreParameters;
013: import java.util.Properties;
014: import java.util.Enumeration;
015: import java.util.List;
016: import java.util.ArrayList;
017:
018: import javax.mail.Message;
019: import javax.mail.Session;
020: import javax.mail.Transport;
021: import javax.mail.internet.InternetAddress;
022: import javax.mail.internet.MimeBodyPart;
023: import javax.mail.internet.MimeMessage;
024: import javax.mail.internet.MimeMultipart;
025: import javax.activation.MailcapCommandMap;
026: import javax.activation.CommandMap;
027:
028: import org.bouncycastle.jce.provider.BouncyCastleProvider;
029: import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator;
030: import org.bouncycastle.mail.smime.SMIMEException;
031: import org.bouncycastle.mail.smime.SMIMESignedGenerator;
032: import org.bouncycastle.util.Strings;
033: import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
034: import org.bouncycastle.asn1.smime.SMIMECapability;
035: import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
036: import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
037: import org.bouncycastle.asn1.ASN1EncodableVector;
038: import org.bouncycastle.asn1.x509.X509Name;
039: import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
040: import org.bouncycastle.asn1.cms.AttributeTable;
041:
042: /**
043: * Example that sends a signed and encrypted mail message.
044: */
045: public class SendSignedAndEncryptedMail {
046: public static void main(String args[]) {
047: if (args.length != 5) {
048: System.err
049: .println("usage: SendSignedAndEncryptedMail <pkcs12Keystore> <password> <keyalias> <smtp server> <email address>");
050: System.exit(0);
051: }
052:
053: try {
054: MailcapCommandMap mailcap = (MailcapCommandMap) CommandMap
055: .getDefaultCommandMap();
056:
057: mailcap
058: .addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
059: mailcap
060: .addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
061: mailcap
062: .addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
063: mailcap
064: .addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
065: mailcap
066: .addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
067:
068: CommandMap.setDefaultCommandMap(mailcap);
069:
070: /* Add BC */
071: Security.addProvider(new BouncyCastleProvider());
072:
073: /* Open the keystore */
074: KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
075: keystore.load(new FileInputStream(args[0]), args[1]
076: .toCharArray());
077: Certificate[] chain = keystore.getCertificateChain(args[2]);
078:
079: /* Get the private key to sign the message with */
080: PrivateKey privateKey = (PrivateKey) keystore.getKey(
081: args[2], args[1].toCharArray());
082: if (privateKey == null) {
083: throw new Exception(
084: "cannot find private key for alias: " + args[2]);
085: }
086:
087: /* Create the message to sign and encrypt */
088: Properties props = System.getProperties();
089: props.put("mail.smtp.host", args[3]);
090: Session session = Session.getDefaultInstance(props, null);
091:
092: MimeMessage body = new MimeMessage(session);
093: body.setFrom(new InternetAddress(args[4]));
094: body.setRecipient(Message.RecipientType.TO,
095: new InternetAddress(args[4]));
096: body.setSubject("example encrypted message");
097: body.setContent("example encrypted message", "text/plain");
098: body.saveChanges();
099:
100: /* Create the SMIMESignedGenerator */
101: SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
102: capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
103: capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
104: capabilities.addCapability(SMIMECapability.dES_CBC);
105:
106: ASN1EncodableVector attributes = new ASN1EncodableVector();
107: attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(
108: new IssuerAndSerialNumber(new X509Name(
109: ((X509Certificate) chain[0]).getIssuerDN()
110: .getName()),
111: ((X509Certificate) chain[0])
112: .getSerialNumber())));
113: attributes
114: .add(new SMIMECapabilitiesAttribute(capabilities));
115:
116: SMIMESignedGenerator signer = new SMIMESignedGenerator();
117: signer
118: .addSigner(
119: privateKey,
120: (X509Certificate) chain[0],
121: "DSA".equals(privateKey.getAlgorithm()) ? SMIMESignedGenerator.DIGEST_SHA1
122: : SMIMESignedGenerator.DIGEST_MD5,
123: new AttributeTable(attributes), null);
124:
125: /* Add the list of certs to the generator */
126: List certList = new ArrayList();
127: certList.add(chain[0]);
128: CertStore certs = CertStore.getInstance("Collection",
129: new CollectionCertStoreParameters(certList), "BC");
130: signer.addCertificatesAndCRLs(certs);
131:
132: /* Sign the message */
133: MimeMultipart mm = signer.generate(body, "BC");
134: MimeMessage signedMessage = new MimeMessage(session);
135:
136: /* Set all original MIME headers in the signed message */
137: Enumeration headers = body.getAllHeaderLines();
138: while (headers.hasMoreElements()) {
139: signedMessage.addHeaderLine((String) headers
140: .nextElement());
141: }
142:
143: /* Set the content of the signed message */
144: signedMessage.setContent(mm);
145: signedMessage.saveChanges();
146:
147: /* Create the encrypter */
148: SMIMEEnvelopedGenerator encrypter = new SMIMEEnvelopedGenerator();
149: encrypter.addKeyTransRecipient((X509Certificate) chain[0]);
150:
151: /* Encrypt the message */
152: MimeBodyPart encryptedPart = encrypter.generate(
153: signedMessage, SMIMEEnvelopedGenerator.RC2_CBC,
154: "BC");
155:
156: /*
157: * Create a new MimeMessage that contains the encrypted and signed
158: * content
159: */
160: ByteArrayOutputStream out = new ByteArrayOutputStream();
161: encryptedPart.writeTo(out);
162:
163: MimeMessage encryptedMessage = new MimeMessage(session,
164: new ByteArrayInputStream(out.toByteArray()));
165:
166: /* Set all original MIME headers in the encrypted message */
167: headers = body.getAllHeaderLines();
168: while (headers.hasMoreElements()) {
169: String headerLine = (String) headers.nextElement();
170: /*
171: * Make sure not to override any content-* headers from the
172: * original message
173: */
174: if (!Strings.toLowerCase(headerLine).startsWith(
175: "content-")) {
176: encryptedMessage.addHeaderLine(headerLine);
177: }
178: }
179:
180: Transport.send(encryptedMessage);
181: } catch (SMIMEException ex) {
182: ex.getUnderlyingException().printStackTrace(System.err);
183: ex.printStackTrace(System.err);
184: } catch (Exception ex) {
185: ex.printStackTrace(System.err);
186: }
187: }
188: }
|