Skip to content

Instantly share code, notes, and snippets.

@siosio
Created August 30, 2012 23:41
Show Gist options
  • Save siosio/3545332 to your computer and use it in GitHub Desktop.
Save siosio/3545332 to your computer and use it in GitHub Desktop.
package mail;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.SignerInfoGenerator;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
import org.bouncycastle.mail.smime.SMIMESignedGenerator;
import org.bouncycastle.mail.smime.SMIMEUtil;
public class BcMailSample {
/** 秘密鍵 */
private PrivateKey key;
/** 証明書 */
private X509Certificate certificate;
public static void main(String[] args) throws Exception {
BcMailSample mail = new BcMailSample();
mail.loadCertificateFile("verisign.p12");
mail.sendSignedMail();
}
/** 証明書付きメールを送信する。 */
private void sendSignedMail() throws Exception {
MimeMessage message = createMimeMessage();
message.saveChanges();
Transport.send(message);
}
/**
* MimeMessageを生成する。
* @return MimeMessage
*/
private MimeMessage createMimeMessage() throws Exception {
Properties properties = new Properties();
properties.put("mail.smtp.host", "****");
properties.put("mail.host", "****");
properties.put("mail.smtp.port", "25");
Session session = Session.getInstance(properties);
MimeMessage message = new MimeMessage(session);
message.setSubject("タイトル", "utf-8");
message.setRecipients(Message.RecipientType.TO, "to");
message.setFrom(new InternetAddress("from"));
message.setContent(createSignedBody());
return message;
}
/**
* 署名付きの本文を生成する。
*/
private Multipart createSignedBody() throws Exception {
MimeBodyPart body = new MimeBodyPart();
body.setText("メール本文", "utf-8");
//--------------------------------------------------------------------------------
// 添付ファイルがある場合ここから
//--------------------------------------------------------------------------------
MimeMultipart multipart = new MimeMultipart();
File file = new File("BcMailSample.java");
ByteArrayDataSource dataSource = new ByteArrayDataSource(new FileInputStream(file), "text/plain");
DataHandler dataHandler = new DataHandler(dataSource);
MimeBodyPart filePart = new MimeBodyPart();
filePart.setDataHandler(dataHandler);
filePart.setFileName("BcMailSample.java");
multipart.addBodyPart(body); // 本文
multipart.addBodyPart(filePart); // 添付ファイル
MimeBodyPart allBody = new MimeBodyPart();
allBody.setContent(multipart);
//--------------------------------------------------------------------------------
// 添付ファイルがある場合ここまで
//--------------------------------------------------------------------------------
SMIMESignedGenerator generator = new SMIMESignedGenerator();
generator.addSignerInfoGenerator(createSignerInfoGenerator());
List<X509Certificate> certificateList = new ArrayList<>();
certificateList.add(certificate);
generator.addCertificates(new JcaCertStore(certificateList));
//return generator.generate(allBody); // 添付ファイル有りの場合
return generator.generate(body);
}
/**
* 電子署名を生成するためのジェネレータを生成する。
*
* @return 電子署名を生成するためのジェネレータ
*/
private SignerInfoGenerator createSignerInfoGenerator() throws Exception {
ASN1EncodableVector encodableVector = new ASN1EncodableVector();
IssuerAndSerialNumber issuerAndSerialNumberFor = SMIMEUtil.createIssuerAndSerialNumberFor(certificate);
encodableVector.add(new SMIMEEncryptionKeyPreferenceAttribute(issuerAndSerialNumberFor));
AttributeTable attributeTable = new AttributeTable(encodableVector);
JcaSimpleSignerInfoGeneratorBuilder simpleSignerInfoGeneratorBuilder = new JcaSimpleSignerInfoGeneratorBuilder();
simpleSignerInfoGeneratorBuilder.setSignedAttributeGenerator(attributeTable);
return simpleSignerInfoGeneratorBuilder.build("SHA1withRSA", key, certificate);
}
/**
* 証明書からもろもろロード。
*
* @param certificateFile 証明書ファイル
*/
private void loadCertificateFile(String certificateFile) throws Exception {
KeyStore keyStore;
try (InputStream stream = new FileInputStream(certificateFile)) {
keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(stream, "password".toCharArray());
}
// キーエントリのエイリアス名を取得
String aliasName = getAliasName(keyStore);
key = (PrivateKey) keyStore.getKey(aliasName, "password".toCharArray());
certificate = (X509Certificate) keyStore.getCertificate(aliasName);
}
/**
* エリアス名を取得する。
*
* @param keyStore キーストア
* @return エリアス名
*/
private String getAliasName(KeyStore keyStore) throws KeyStoreException {
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if (keyStore.isKeyEntry(alias)) {
return alias;
}
}
throw new IllegalArgumentException("key entry was not found.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment