使用BouncyCastle使用SMIME和X.509加密邮件 [英] Encrypt mail with SMIME and X.509 using BouncyCastle

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

问题描述

我正在尝试使用JavaMail库和BouncyCastle库发送加密的邮件:

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

这是我编写的代码,或者我遵循了教程:

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();

这是我从达尔维克获得的唯一错误消息:

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文件都位于文件夹libs下.

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 are trying to achieve, is not just encrypting a MIME message, you want to sign and encrypt it (and it must be done in that order)

BouncyCastle提供的电子邮件签名示例为此处

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

最后,对BodyPart进行签名会为您提供一个Multipart,您必须将其包装在要加密的MimeBodyPart中,这将为您提供一个加密的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天全站免登陆