~brian-thomason/+junk/bouncycastle

« back to all changes in this revision

Viewing changes to src/org/bouncycastle/mail/smime/examples/CreateLargeSignedMail.java

  • Committer: Brian Thomason
  • Date: 2011-12-20 17:20:32 UTC
  • Revision ID: brian.thomason@canonical.com-20111220172032-rdtm13jgdxtksacr
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.bouncycastle.mail.smime.examples;
 
2
 
 
3
import java.io.ByteArrayInputStream;
 
4
import java.io.File;
 
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;
 
19
 
 
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;
 
29
 
 
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;
 
53
 
 
54
/**
 
55
 * a simple example that creates a single signed mail message.
 
56
 */
 
57
public class CreateLargeSignedMail
 
58
{
 
59
    //
 
60
    // certificate serial number seed.
 
61
    //
 
62
    static int  serialNo = 1;
 
63
 
 
64
    static AuthorityKeyIdentifier createAuthorityKeyId(
 
65
        PublicKey pub) 
 
66
        throws IOException
 
67
    {
 
68
        ByteArrayInputStream bIn = new ByteArrayInputStream(pub.getEncoded());
 
69
        SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
 
70
            (ASN1Sequence)new ASN1InputStream(bIn).readObject());
 
71
 
 
72
        return new AuthorityKeyIdentifier(info);
 
73
    }
 
74
 
 
75
    static SubjectKeyIdentifier createSubjectKeyId(
 
76
        PublicKey pub) 
 
77
        throws IOException
 
78
    {
 
79
        ByteArrayInputStream bIn = new ByteArrayInputStream(pub.getEncoded());
 
80
 
 
81
        SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
 
82
            (ASN1Sequence)new ASN1InputStream(bIn).readObject());
 
83
 
 
84
        return new SubjectKeyIdentifier(info);
 
85
    }
 
86
 
 
87
    /**
 
88
     * create a basic X509 certificate from the given keys
 
89
     */
 
90
    static X509Certificate makeCertificate(
 
91
        KeyPair subKP,
 
92
        String  subDN,
 
93
        KeyPair issKP,
 
94
        String  issDN)
 
95
        throws GeneralSecurityException, IOException, OperatorCreationException
 
96
    {
 
97
        PublicKey  subPub  = subKP.getPublic();
 
98
        PrivateKey issPriv = issKP.getPrivate();
 
99
        PublicKey  issPub  = issKP.getPublic();
 
100
 
 
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);
 
102
 
 
103
        v3CertGen.addExtension(
 
104
            X509Extension.subjectKeyIdentifier,
 
105
            false,
 
106
            createSubjectKeyId(subPub));
 
107
 
 
108
        v3CertGen.addExtension(
 
109
            X509Extension.authorityKeyIdentifier,
 
110
            false,
 
111
            createAuthorityKeyId(issPub));
 
112
 
 
113
        return new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
 
114
    }
 
115
 
 
116
    public static void main(
 
117
        String args[])
 
118
        throws Exception
 
119
    {
 
120
        //
 
121
        // set up our certs
 
122
        //
 
123
        KeyPairGenerator    kpg  = KeyPairGenerator.getInstance("RSA", "BC");
 
124
 
 
125
        kpg.initialize(1024, new SecureRandom());
 
126
 
 
127
        //
 
128
        // cert that issued the signing certificate
 
129
        //
 
130
        String              signDN = "O=Bouncy Castle, C=AU";
 
131
        KeyPair             signKP = kpg.generateKeyPair();
 
132
        X509Certificate     signCert = makeCertificate(
 
133
                                        signKP, signDN, signKP, signDN);
 
134
 
 
135
        //
 
136
        // cert we sign against
 
137
        //
 
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);
 
142
 
 
143
        List                certList = new ArrayList();
 
144
 
 
145
        certList.add(origCert);
 
146
        certList.add(signCert);
 
147
 
 
148
        //
 
149
        // create a CertStore containing the certificates we want carried
 
150
        // in the signature
 
151
        //
 
152
        Store certs = new JcaCertStore(certList);
 
153
 
 
154
        //
 
155
        // create some smime capabilities in case someone wants to respond
 
156
        //
 
157
        ASN1EncodableVector         signedAttrs = new ASN1EncodableVector();
 
158
        SMIMECapabilityVector       caps = new SMIMECapabilityVector();
 
159
 
 
160
        caps.addCapability(SMIMECapability.dES_EDE3_CBC);
 
161
        caps.addCapability(SMIMECapability.rC2_CBC, 128);
 
162
        caps.addCapability(SMIMECapability.dES_CBC);
 
163
 
 
164
        signedAttrs.add(new SMIMECapabilitiesAttribute(caps));
 
165
 
 
166
        //
 
167
        // add an encryption key preference for encrypted responses -
 
168
        // normally this would be different from the signing certificate...
 
169
        //
 
170
        IssuerAndSerialNumber   issAndSer = new IssuerAndSerialNumber(
 
171
                new X500Name(signDN), origCert.getSerialNumber());
 
172
 
 
173
        signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(issAndSer));
 
174
 
 
175
        //
 
176
        // create the generator for creating an smime/signed message
 
177
        //
 
178
        SMIMESignedGenerator gen = new SMIMESignedGenerator();
 
179
 
 
180
        //
 
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
 
185
        //
 
186
        gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA1withRSA", origKP.getPrivate(), origCert));
 
187
 
 
188
        //
 
189
        // add our pool of certs and cerls (if any) to go with the signature
 
190
        //
 
191
        gen.addCertificates(certs);
 
192
 
 
193
        //
 
194
        // create the base for our message
 
195
        //
 
196
        MimeBodyPart    msg = new MimeBodyPart();
 
197
 
 
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");
 
201
 
 
202
        //
 
203
        // extract the multipart object from the SMIMESigned object.
 
204
        //
 
205
        MimeMultipart mm = gen.generate(msg);
 
206
 
 
207
        //
 
208
        // Get a Session object and create the mail message
 
209
        //
 
210
        Properties props = System.getProperties();
 
211
        Session session = Session.getDefaultInstance(props, null);
 
212
 
 
213
        Address fromUser = new InternetAddress("\"Eric H. Echidna\"<eric@bouncycastle.org>");
 
214
        Address toUser = new InternetAddress("example@bouncycastle.org");
 
215
 
 
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());
 
221
        body.saveChanges();
 
222
 
 
223
        body.writeTo(new FileOutputStream("signed.message"));
 
224
    }
 
225
}