1
package org.bouncycastle.mail.smime.examples;
3
import java.io.ByteArrayInputStream;
5
import java.io.FileOutputStream;
6
import java.io.IOException;
7
import java.math.BigInteger;
8
import java.security.GeneralSecurityException;
9
import java.security.KeyPair;
10
import java.security.KeyPairGenerator;
11
import java.security.PrivateKey;
12
import java.security.PublicKey;
13
import java.security.SecureRandom;
14
import java.security.cert.X509Certificate;
15
import java.util.ArrayList;
16
import java.util.Date;
17
import java.util.List;
18
import java.util.Properties;
20
import javax.activation.DataHandler;
21
import javax.activation.FileDataSource;
22
import javax.mail.Address;
23
import javax.mail.Message;
24
import javax.mail.Session;
25
import javax.mail.internet.InternetAddress;
26
import javax.mail.internet.MimeBodyPart;
27
import javax.mail.internet.MimeMessage;
28
import javax.mail.internet.MimeMultipart;
30
import org.bouncycastle.asn1.ASN1EncodableVector;
31
import org.bouncycastle.asn1.ASN1InputStream;
32
import org.bouncycastle.asn1.ASN1Sequence;
33
import org.bouncycastle.asn1.cms.AttributeTable;
34
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
35
import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
36
import org.bouncycastle.asn1.smime.SMIMECapability;
37
import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
38
import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
39
import org.bouncycastle.asn1.x500.X500Name;
40
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
41
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
42
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
43
import org.bouncycastle.asn1.x509.X509Extension;
44
import org.bouncycastle.cert.X509v3CertificateBuilder;
45
import org.bouncycastle.cert.jcajce.JcaCertStore;
46
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
47
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
48
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
49
import org.bouncycastle.mail.smime.SMIMESignedGenerator;
50
import org.bouncycastle.operator.OperatorCreationException;
51
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
52
import org.bouncycastle.util.Store;
55
* a simple example that creates a single signed mail message.
57
public class CreateLargeSignedMail
60
// certificate serial number seed.
62
static int serialNo = 1;
64
static AuthorityKeyIdentifier createAuthorityKeyId(
68
ByteArrayInputStream bIn = new ByteArrayInputStream(pub.getEncoded());
69
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
70
(ASN1Sequence)new ASN1InputStream(bIn).readObject());
72
return new AuthorityKeyIdentifier(info);
75
static SubjectKeyIdentifier createSubjectKeyId(
79
ByteArrayInputStream bIn = new ByteArrayInputStream(pub.getEncoded());
81
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
82
(ASN1Sequence)new ASN1InputStream(bIn).readObject());
84
return new SubjectKeyIdentifier(info);
88
* create a basic X509 certificate from the given keys
90
static X509Certificate makeCertificate(
95
throws GeneralSecurityException, IOException, OperatorCreationException
97
PublicKey subPub = subKP.getPublic();
98
PrivateKey issPriv = issKP.getPrivate();
99
PublicKey issPub = issKP.getPublic();
101
X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(new X500Name(issDN), BigInteger.valueOf(serialNo++), new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), new X500Name(subDN), subPub);
103
v3CertGen.addExtension(
104
X509Extension.subjectKeyIdentifier,
106
createSubjectKeyId(subPub));
108
v3CertGen.addExtension(
109
X509Extension.authorityKeyIdentifier,
111
createAuthorityKeyId(issPub));
113
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
116
public static void main(
123
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
125
kpg.initialize(1024, new SecureRandom());
128
// cert that issued the signing certificate
130
String signDN = "O=Bouncy Castle, C=AU";
131
KeyPair signKP = kpg.generateKeyPair();
132
X509Certificate signCert = makeCertificate(
133
signKP, signDN, signKP, signDN);
136
// cert we sign against
138
String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
139
KeyPair origKP = kpg.generateKeyPair();
140
X509Certificate origCert = makeCertificate(
141
origKP, origDN, signKP, signDN);
143
List certList = new ArrayList();
145
certList.add(origCert);
146
certList.add(signCert);
149
// create a CertStore containing the certificates we want carried
152
Store certs = new JcaCertStore(certList);
155
// create some smime capabilities in case someone wants to respond
157
ASN1EncodableVector signedAttrs = new ASN1EncodableVector();
158
SMIMECapabilityVector caps = new SMIMECapabilityVector();
160
caps.addCapability(SMIMECapability.dES_EDE3_CBC);
161
caps.addCapability(SMIMECapability.rC2_CBC, 128);
162
caps.addCapability(SMIMECapability.dES_CBC);
164
signedAttrs.add(new SMIMECapabilitiesAttribute(caps));
167
// add an encryption key preference for encrypted responses -
168
// normally this would be different from the signing certificate...
170
IssuerAndSerialNumber issAndSer = new IssuerAndSerialNumber(
171
new X500Name(signDN), origCert.getSerialNumber());
173
signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(issAndSer));
176
// create the generator for creating an smime/signed message
178
SMIMESignedGenerator gen = new SMIMESignedGenerator();
181
// add a signer to the generator - this specifies we are using SHA1 and
182
// adding the smime attributes above to the signed attributes that
183
// will be generated as part of the signature. The encryption algorithm
184
// used is taken from the key - in this RSA with PKCS1Padding
186
gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA1withRSA", origKP.getPrivate(), origCert));
189
// add our pool of certs and cerls (if any) to go with the signature
191
gen.addCertificates(certs);
194
// create the base for our message
196
MimeBodyPart msg = new MimeBodyPart();
198
msg.setDataHandler(new DataHandler(new FileDataSource(new File(args[0]))));
199
msg.setHeader("Content-Type", "application/octet-stream");
200
msg.setHeader("Content-Transfer-Encoding", "base64");
203
// extract the multipart object from the SMIMESigned object.
205
MimeMultipart mm = gen.generate(msg);
208
// Get a Session object and create the mail message
210
Properties props = System.getProperties();
211
Session session = Session.getDefaultInstance(props, null);
213
Address fromUser = new InternetAddress("\"Eric H. Echidna\"<eric@bouncycastle.org>");
214
Address toUser = new InternetAddress("example@bouncycastle.org");
216
MimeMessage body = new MimeMessage(session);
217
body.setFrom(fromUser);
218
body.setRecipient(Message.RecipientType.TO, toUser);
219
body.setSubject("example signed message");
220
body.setContent(mm, mm.getContentType());
223
body.writeTo(new FileOutputStream("signed.message"));