Encrypt mail using SMIME and X.509 using BouncyCastle

I am trying to send encrypted mail using JavaMail Library and BouncyCastle Library:

This is the code I wrote or I completed the 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 application crashes in the 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> 

All my external .jar files are under the libs folder.

Does anyone know why this is happening? Has anyone succeeded in encrypting mail using SMIME / X.509? Or is there a much easier way to do this?

+4
source share
1 answer

If I understand what you are trying to achieve, you are not just encrypting the MIME message, you are signing and encrypting it (and this should be done in that order)

BouncyCastle provided an example for signing an email here BouncyCastle provided an example for signing an email here

Finally, signing BodyPart gives you Multipart, which you have to wrap in MimeBodyPart, which you will encrypt, and get the encrypted MimeBodyPart, which you β€œinsert” into MimeMessage (see the encryption example).

+8
source

Source: https://habr.com/ru/post/1432709/


All Articles