BouncyCastle的加密邮件与SMIME和X.509 [英] BouncyCastle Encrypt mail with SMIME and X.509

查看:874
本文介绍了BouncyCastle的加密邮件与SMIME和X.509的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图发送加密邮件与的JavaMail 库和 BouncyCastle的库:

I'm trying to send a encrypted mail with JavaMail Library and BouncyCastle Library:

这是在code我已经写了,或者我也跟着教程:

This is the code I've written, or I followed a tutorial:

public class SendMail extends javax.mail.Authenticator {

private String _user;
private String _pass;

private String[] _to;
private String _from;

private String _port;
private String _sport;

private String _host;

private String _subject;
private String _body;

private boolean _auth;
private boolean _debuggable;

private Multipart _multipart;
SharedPreferences sharedPrefs;

InputStream privateKeyStoreInputStream;
InputStream publicCertificateInputStream;
InputStream publicKeystoreInputStream;

public static final String ksPassword = "mobile";
Certificate[] chain;
PrivateKey privateKey;
Certificate rcptCert;
CertificateFactory cf;

public SendMail() {

    _user = ""; // username
    _pass = ""; // password
    _from = ""; // email sent from
    _subject = ""; // email subject
    _body = ""; // email body

    _debuggable = false; // debug mode on or off - default off
    _auth = true; // smtp authentication - default on

    _multipart = new MimeMultipart();

    // There is something wrong with MailCap, javamail can not find a
    // handler for the multipart/mixed part, so this bit needs to be added.
    MailcapCommandMap mc = (MailcapCommandMap) CommandMap
            .getDefaultCommandMap();
    mc.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
    mc.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
    mc.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
    mc.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
    mc.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");

    CommandMap.setDefaultCommandMap(mc);

    Security.addProvider(new BouncyCastleProvider());

}

public SendMail(Context c, InputStream privateKeyStoreInputStream,
        InputStream publicCertificateInputStream,
        InputStream publicKeystoreInputStream) {
    this();

    this.privateKeyStoreInputStream = privateKeyStoreInputStream;
    this.publicCertificateInputStream = publicCertificateInputStream;
    this.publicKeystoreInputStream = publicKeystoreInputStream;

    _host = "removed";
    _port = "25";
    _sport = "25";
    _user = "removed";
    _pass = "removed";

    try {
        KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
        keystore.load(privateKeyStoreInputStream, ksPassword.toCharArray());

        Enumeration e = keystore.aliases();
        String keyAlias = null;

        while (e.hasMoreElements() && (keyAlias == null)) {
            String alias = (String) e.nextElement();
            keyAlias = keystore.isKeyEntry(alias) ? alias : null;
        }

        if (keyAlias == null) {
            Log.e("KEY ALIAS: ", "NULL");
            return;
        }

        chain = keystore.getCertificateChain(keyAlias);

        /* Get the private key to sign the message */

        privateKey = (PrivateKey) keystore.getKey(keyAlias,
                ksPassword.toCharArray());

        if (privateKey == null) {
            Log.e("No Private key for: ", keyAlias);
        }

        /* Get the public key of reciepient */
        BufferedInputStream bis = new BufferedInputStream(
                publicCertificateInputStream);
        cf = CertificateFactory.getInstance("X.509");
        rcptCert = cf.generateCertificate(bis);

    } catch (KeyStoreException e) {
        Log.e("KeyStore Exception: ", e.getMessage());
    } catch (NoSuchProviderException e) {
        Log.e("NoSuchProvider Exception: ", e.getMessage());
    } catch (CertificateException ce) {
        Log.e("Certification Exception: ", ce.getMessage());
    } catch (NoSuchAlgorithmException ns) {
        Log.e("NoSuchAlgorithm Exception: ", ns.getMessage());
    } catch (IOException e) {
        Log.e("IO Exception: ", e.getMessage());
    } catch (UnrecoverableKeyException uke) {
        Log.e("UnrecoverableKeyException: ", uke.getMessage());
    }
}

public boolean send() throws Exception {
    Properties props = _setProperties();

    if (!_user.equals("") && !_pass.equals("") && _to.length > 0
            && !_from.equals("") && !_subject.equals("")
            && !_body.equals("")) {

        Session session = Session.getInstance(props,
                new GMailAuthenticator(_user, _pass));

        MimeMessage msg = new MimeMessage(session);

        msg.setFrom(new InternetAddress(_from));

        InternetAddress[] addressTo = new InternetAddress[_to.length];
        for (int i = 0; i < _to.length; i++) {
            addressTo[i] = new InternetAddress(_to[i]);
        }
        msg.setRecipients(MimeMessage.RecipientType.TO, addressTo);

        msg.setSubject(_subject);
        msg.setSentDate(new Date());

        // setup message body
        BodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setText(_body);
        _multipart.addBodyPart(messageBodyPart);

        // Put parts in message
        msg.setContent(_multipart);

        /* Create SMIMESignedGenerator */
        SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
        capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
        capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
        capabilities.addCapability(SMIMECapability.dES_CBC);

        ASN1EncodableVector attributes = new ASN1EncodableVector();
        // attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(new
        // org.bouncycastle.asn1.cms.IssuerAndSerialNumber(new
        // X509Name(((X509Certificate)chain[0]).getIssuerDN().getName()),
        // ((X509Certificate)chain[0]).getSerialNumber())));
        attributes.add(new SMIMECapabilitiesAttribute(capabilities));

        SMIMESignedGenerator signer = new SMIMESignedGenerator();

        signer.addSigner(
                privateKey,
                (X509Certificate) chain[0],
                "DSA".equals(privateKey.getAlgorithm()) ? SMIMESignedGenerator.DIGEST_SHA1
                        : SMIMESignedGenerator.DIGEST_MD5,
                new AttributeTable(attributes), null);

        /* Add the list of certs to the generator */
        List certList = new ArrayList();
        certList.add(chain[0]);
        CertStore certs = CertStore.getInstance("Collection",
                new CollectionCertStoreParameters(certList), "BC");
        signer.addCertificatesAndCRLs(certs);

        /* Sign the message and copy all headers from original message */
        MimeMultipart multipart = signer.generate(msg, "BC");
        MimeMessage signedMessage = new MimeMessage(session);
        Enumeration headers = msg.getAllHeaderLines();

        while (headers.hasMoreElements()) {
            signedMessage.addHeaderLine((String) headers.nextElement());
        }

        signedMessage.setContent(_multipart);
        signedMessage.saveChanges();

        /* Create the encrypter and encrypt the message */
        SMIMEEnvelopedGenerator encrypter = new SMIMEEnvelopedGenerator();
        encrypter.addKeyTransRecipient((X509Certificate) chain[0]);
        encrypter.addKeyTransRecipient((X509Certificate) rcptCert);

        MimeBodyPart encryptedPart = encrypter.generate(signedMessage,
                SMIMEEnvelopedGenerator.RC2_CBC, 128, "BC");
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        encryptedPart.writeTo(out);

        Session smtpSession = Session.getInstance(props, null);
        MimeMessage smtpMessage = new MimeMessage(smtpSession,
                new ByteArrayInputStream(out.toByteArray()));
        smtpMessage.saveChanges();

        Transport.send(smtpMessage);

        return true;
    } else {
        return false;
    }
}

public void addAttachment(String filename) throws Exception {
    BodyPart messageBodyPart = new MimeBodyPart();
    DataSource source = new FileDataSource(filename);
    messageBodyPart.setDataHandler(new DataHandler(source));
    messageBodyPart.setFileName(filename);

    _multipart.addBodyPart(messageBodyPart);
}

class GMailAuthenticator extends Authenticator {
    String user;
    String pw;

    public GMailAuthenticator(String username, String password) {
        super();
        this.user = username;
        this.pw = password;
    }

    public PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(user, pw);
    }
}

private Properties _setProperties() {
    Properties props = new Properties();

    props.put("mail.smtp.host", _host);
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.connectiontimeout", "20000"); // timeout with mail
                                                        // 20 sec.

    if (_debuggable) {
        props.put("mail.debug", "true");
    }

    if (_auth) {
        props.put("mail.smtp.auth", "true");
    }

    props.put("mail.smtp.port", _port);
    props.put("mail.smtp.socketFactory.port", _sport);
    props.put("mail.smtp.socketFactory.fallback", "true");

    return props;
}

public String getBody() {
    return _body;
}

public void setBody(String _body) {
    this._body = _body;
}

public void setTo(String[] toArr) {
    this._to = toArr;
}

public void setFrom(String string) {
    this._from = string;
}

public void setSubject(String string) {
    this._subject = string;
}
}

当我调试应用程序,唯一的应用程序崩溃,在此以下行:

When I debug the application, the only app crashes at this following line:

SMIMESignedGenerator signer = new SMIMESignedGenerator();

这是我Dalvik的得到的唯一错误消息:

This is the only error message I get from dalvik:

DexOpt: unable to optimize static field ref 0x0991 at 0x18 in Lorg/bouncycastle/mail/smime/SMIMESignedGenerator;.<clinit>

我所有的外部的.jar 文件所在的文件夹下

All of my external .jar files is located under the folder libs.

是否有人知道为什么会这样?已经有人成功了加密与SMIME / X.509邮件?或者是有一个更简单的方法来做到这一点?

Does anybody know why this happens? Have anybody succeeded encrypting a mail with SMIME/X.509? Or is there a much simpler way to do this?

推荐答案

如果我明白你想实现的,你不只是加密MIME消息,你是签名和加密(并且必须按照这个顺序做)

If I understand what you try to achieve, you are not just encrypting a MIME message, you are signing and encrypting it (and it must be done in that order)

该BouncyCastle的规定为例,签署电子邮件是<一个href="http://www.docjar.org/src/api/org/bouncycastle/mail/smime/examples/CreateSignedMail.java">here 该BouncyCastle的提供的例子来加密电子邮件是<一个href="http://www.docjar.org/src/api/org/bouncycastle/mail/smime/examples/CreateEncryptedMail.java">here

The BouncyCastle provided example to signing an email is here The BouncyCastle provided example to encrypting an email is here

最后,签订BodyPart的让你一个多部分,你必须包装在一个MimeBodyPart你加密,它可以让你的加密MimeBodyPart你在的MimeMessage插入(见加密例子)

Finally, signing a BodyPart gets you a Multipart that you must wrap in a MimeBodyPart that you encrypt, which gets you an encrypted MimeBodyPart which you "insert" in a MimeMessage (see encryption example)

这篇关于BouncyCastle的加密邮件与SMIME和X.509的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆