我正在尝试使用JavaMailLibrary和BouncyCastleLibrary 发送加密的邮件:
JavaMail
BouncyCastle
这是我编写的代码,或者我遵循了一个教程:
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; } }
当我调试应用程序时,唯一的应用程序在以下行崩溃:
SMIMESignedGenerator signer = new SMIMESignedGenerator();
这是我从达尔维克获得的唯一错误消息:
DexOpt: unable to optimize static field ref 0x0991 at 0x18 in Lorg/bouncycastle/mail/smime/SMIMESignedGenerator;.<clinit>
我所有的外部.jar文件都位于该文件夹下libs。
.jar
libs
有人知道为什么会这样吗?有没有人成功使用SMIME / X.509加密邮件?还是有更简单的方法来做到这一点?
如果我了解您要实现的目标,不仅是对MIME消息进行加密,还需要对其进行签名和加密(并且必须按此顺序进行)
BouncyCastle提供的用于签名电子邮件的示例在此处 BouncyCastle提供的用于加密电子邮件的示例在此处
最后,签名BodyPart会得到一个Multipart,您必须将其包装在要加密的MimeBodyPart中,这会为您提供一个加密的MimeBodyPart,您将该MimeBodyPart“插入”在MimeMessage中(请参见加密示例)。