001: package org.bouncycastle.mail.smime.examples;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.File;
005: import java.io.FileOutputStream;
006: import java.io.IOException;
007: import java.math.BigInteger;
008: import java.security.GeneralSecurityException;
009: import java.security.KeyPair;
010: import java.security.KeyPairGenerator;
011: import java.security.PrivateKey;
012: import java.security.PublicKey;
013: import java.security.SecureRandom;
014: import java.security.cert.CertStore;
015: import java.security.cert.CollectionCertStoreParameters;
016: import java.security.cert.X509Certificate;
017: import java.util.ArrayList;
018: import java.util.Date;
019: import java.util.List;
020: import java.util.Properties;
021:
022: import javax.activation.DataHandler;
023: import javax.activation.FileDataSource;
024: import javax.mail.Address;
025: import javax.mail.Message;
026: import javax.mail.Session;
027: import javax.mail.internet.InternetAddress;
028: import javax.mail.internet.MimeBodyPart;
029: import javax.mail.internet.MimeMessage;
030: import javax.mail.internet.MimeMultipart;
031:
032: import org.bouncycastle.asn1.ASN1EncodableVector;
033: import org.bouncycastle.asn1.ASN1InputStream;
034: import org.bouncycastle.asn1.ASN1Sequence;
035: import org.bouncycastle.asn1.cms.AttributeTable;
036: import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
037: import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
038: import org.bouncycastle.asn1.smime.SMIMECapability;
039: import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
040: import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
041: import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
042: import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
043: import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
044: import org.bouncycastle.asn1.x509.X509Extensions;
045: import org.bouncycastle.asn1.x509.X509Name;
046: import org.bouncycastle.x509.X509V3CertificateGenerator;
047: import org.bouncycastle.mail.smime.SMIMESignedGenerator;
048:
049: /**
050: * a simple example that creates a single signed mail message.
051: */
052: public class CreateLargeSignedMail {
053: //
054: // certificate serial number seed.
055: //
056: static int serialNo = 1;
057:
058: static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey pub)
059: throws IOException {
060: ByteArrayInputStream bIn = new ByteArrayInputStream(pub
061: .getEncoded());
062: SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
063: (ASN1Sequence) new ASN1InputStream(bIn).readObject());
064:
065: return new AuthorityKeyIdentifier(info);
066: }
067:
068: static SubjectKeyIdentifier createSubjectKeyId(PublicKey pub)
069: throws IOException {
070: ByteArrayInputStream bIn = new ByteArrayInputStream(pub
071: .getEncoded());
072:
073: SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
074: (ASN1Sequence) new ASN1InputStream(bIn).readObject());
075:
076: return new SubjectKeyIdentifier(info);
077: }
078:
079: /**
080: * create a basic X509 certificate from the given keys
081: */
082: static X509Certificate makeCertificate(KeyPair subKP, String subDN,
083: KeyPair issKP, String issDN)
084: throws GeneralSecurityException, IOException {
085: PublicKey subPub = subKP.getPublic();
086: PrivateKey issPriv = issKP.getPrivate();
087: PublicKey issPub = issKP.getPublic();
088:
089: X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
090:
091: v3CertGen.setSerialNumber(BigInteger.valueOf(serialNo++));
092: v3CertGen.setIssuerDN(new X509Name(issDN));
093: v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
094: v3CertGen.setNotAfter(new Date(System.currentTimeMillis()
095: + (1000L * 60 * 60 * 24 * 100)));
096: v3CertGen.setSubjectDN(new X509Name(subDN));
097: v3CertGen.setPublicKey(subPub);
098: v3CertGen.setSignatureAlgorithm("MD5WithRSAEncryption");
099:
100: v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier,
101: false, createSubjectKeyId(subPub));
102:
103: v3CertGen.addExtension(X509Extensions.AuthorityKeyIdentifier,
104: false, createAuthorityKeyId(issPub));
105:
106: return v3CertGen.generateX509Certificate(issPriv);
107: }
108:
109: public static void main(String args[]) throws Exception {
110: //
111: // set up our certs
112: //
113: KeyPairGenerator kpg = KeyPairGenerator
114: .getInstance("RSA", "BC");
115:
116: kpg.initialize(1024, new SecureRandom());
117:
118: //
119: // cert that issued the signing certificate
120: //
121: String signDN = "O=Bouncy Castle, C=AU";
122: KeyPair signKP = kpg.generateKeyPair();
123: X509Certificate signCert = makeCertificate(signKP, signDN,
124: signKP, signDN);
125:
126: //
127: // cert we sign against
128: //
129: String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
130: KeyPair origKP = kpg.generateKeyPair();
131: X509Certificate origCert = makeCertificate(origKP, origDN,
132: signKP, signDN);
133:
134: List certList = new ArrayList();
135:
136: certList.add(origCert);
137: certList.add(signCert);
138:
139: //
140: // create a CertStore containing the certificates we want carried
141: // in the signature
142: //
143: CertStore certsAndcrls = CertStore.getInstance("Collection",
144: new CollectionCertStoreParameters(certList), "BC");
145:
146: //
147: // create some smime capabilities in case someone wants to respond
148: //
149: ASN1EncodableVector signedAttrs = new ASN1EncodableVector();
150: SMIMECapabilityVector caps = new SMIMECapabilityVector();
151:
152: caps.addCapability(SMIMECapability.dES_EDE3_CBC);
153: caps.addCapability(SMIMECapability.rC2_CBC, 128);
154: caps.addCapability(SMIMECapability.dES_CBC);
155:
156: signedAttrs.add(new SMIMECapabilitiesAttribute(caps));
157:
158: //
159: // add an encryption key preference for encrypted responses -
160: // normally this would be different from the signing certificate...
161: //
162: IssuerAndSerialNumber issAndSer = new IssuerAndSerialNumber(
163: new X509Name(signDN), origCert.getSerialNumber());
164:
165: signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(
166: issAndSer));
167:
168: //
169: // create the generator for creating an smime/signed message
170: //
171: SMIMESignedGenerator gen = new SMIMESignedGenerator();
172:
173: //
174: // add a signer to the generator - this specifies we are using SHA1 and
175: // adding the smime attributes above to the signed attributes that
176: // will be generated as part of the signature. The encryption algorithm
177: // used is taken from the key - in this RSA with PKCS1Padding
178: //
179: gen.addSigner(origKP.getPrivate(), origCert,
180: SMIMESignedGenerator.DIGEST_SHA1, new AttributeTable(
181: signedAttrs), null);
182:
183: //
184: // add our pool of certs and cerls (if any) to go with the signature
185: //
186: gen.addCertificatesAndCRLs(certsAndcrls);
187:
188: //
189: // create the base for our message
190: //
191: MimeBodyPart msg = new MimeBodyPart();
192:
193: msg.setDataHandler(new DataHandler(new FileDataSource(new File(
194: args[0]))));
195: msg.setHeader("Content-Type", "application/octet-stream");
196: msg.setHeader("Content-Transfer-Encoding", "base64");
197:
198: //
199: // extract the multipart object from the SMIMESigned object.
200: //
201: MimeMultipart mm = gen.generate(msg, "BC");
202:
203: //
204: // Get a Session object and create the mail message
205: //
206: Properties props = System.getProperties();
207: Session session = Session.getDefaultInstance(props, null);
208:
209: Address fromUser = new InternetAddress(
210: "\"Eric H. Echidna\"<eric@bouncycastle.org>");
211: Address toUser = new InternetAddress("example@bouncycastle.org");
212:
213: MimeMessage body = new MimeMessage(session);
214: body.setFrom(fromUser);
215: body.setRecipient(Message.RecipientType.TO, toUser);
216: body.setSubject("example signed message");
217: body.setContent(mm, mm.getContentType());
218: body.saveChanges();
219:
220: body.writeTo(new FileOutputStream("signed.message"));
221: }
222: }
|