Created
August 30, 2012 23:41
-
-
Save siosio/3545332 to your computer and use it in GitHub Desktop.
Bouncy Castle Crypto API(http://www.bouncycastle.org/java.html)を使った電子署名付きメール送信。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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