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>
All of my external .jar
files is located under the folder libs
.
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?
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)
The BouncyCastle provided example to signing an email is here The BouncyCastle provided example to encrypting an email is here
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With