How to send a mail with Java that uses S/Mime (2)?
Hello!I have a assignment where I shall create a small app that sends a email signed and encrypted with S/MIME. But I do not manage to create the keys and certificates. I guess my code is correct, it is build with samples from:
http://www.wedgetail.com/jcsi/examples/JCSI-S-MIME-Example.html
To run it you need the jar files:
jcsi_base.jar
jcsi_jce.jar
jcsi_provider.jar
jcsi_smime.jar
...from that site
I'm pretty sure that I mess this up when I try to create the keys and certificates.
Below is my steps for creating the keys and certificates, I guess something is wrong there. After everything is my code, that uses this. So by follow theses steps you should be able to try this.
1 //Create keystore with sender_keypair
keytool -genkey -keyalg "RSA" -alias sender_keypair -keystore smime_keystore -keypass password -dname "cn=Fredrik_Andersson_Sender" -storepass password -storetype pkcs12
2 //Create a certificate request for the sender_keypair
keytool -certreq -alias sender_keypair -file sender_keypair_certrequest.csr -keypass password -storetype pkcs12 -keystore smime_keystore -storepass password
3 //Create the certificate from ca by upload this request at wwww.thawte.com
trials > free trail certificate ...
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIBYTCBywIBADAjMSEwHwYDVQQDDBhGcmVkcmlrX0FuZGVyc3Nvbl9TZW5kZXIwgZ4wDQYJKoZI
hvcNAQEBBQADgYwAMIGIAoGAV2SKsV3Q+V6ykSVx63PpeHz0RoVXOv42HAHjDfO1yjMn7DS/oHkN
Xtte+1un0idCTL6zpQ0EKXAQNbLQOSptbUjKCJLblkBMfkRphBJja38GVfevSCxOE20pbnXGqyRI
F7ugPzNXxvN5lV2mQqWBgO90CJIdhOiHg+04WsvuUnMCAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB
AET/U+0h1U+sbCwmsx1dyYXlr/N4i/e7sbHBHvCAj1FgnxQ/F7W9X43bGBWlpG6rca0Vs6lyF9C2
P4swxhiRMJxLUdz0coPrhtFzjUD8rWOYgBGaTKJCCVbMqOS4D40le6DzAoZsyRzxg7NT17t+QWFn
jiyNC+uLM2jz2j9DAoyI
-----END NEW CERTIFICATE REQUEST-----
For response I get the certificate, is that what they call the ca.certificate?
4 //Create the sender-certificate
keytool -export -keystore smime_keystore -storepass password -alias sender_keypair -file SenderCertificate.cer -storetype pkcs12
5 //Create the receiver_keypair (I will just test local so I store it in the same keystore)
keytool -genkey -keyalg "RSA" -alias receiver_keypair -keystore smime_keystore -keypass password -dname "cn=Fredrik_Andersson_Receiver" -storepass password -storetype pkcs12
6 //Create the receiver-certificate
keytool -export -keystore smime_keystore -storepass password -alias receiver_keypair -file ReceiverCertificate.cer -storetype pkcs12
And the questions....
1) Does this looks like the correct way of doing this or do I have to import the thing I got from thawte into my keystore? Cause when I tried that it said some IOexception like "DerInputStream.getLength(): lengthTag=109, too big"
2) Do I need to connect the sender-certificate with the ca-certificate in some way? Or is that what happens in point 3?
3) When i run my code below I get the following exception, but the exception never looks like it refers to my code. So what do you think is the error?
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.lang.CharacterDataLatin1.getType(CharacterDataLatin1.java:62)
at java.lang.CharacterDataLatin1.isLetter(CharacterDataLatin1.java:91)
at java.lang.Character.isLetter(Character.java:3427)
at java.lang.Character.isLetter(Character.java:3391)
at java.net.URL.isValidProtocol(URL.java:613)
at java.net.URL.<init>(URL.java:529)
at java.net.URL.<init>(URL.java:464)
at java.net.URL.<init>(URL.java:413)
at java.net.JarURLConnection.parseSpecs(JarURLConnection.java:160)
at java.net.JarURLConnection.<init>(JarURLConnection.java:143)
at sun.net.www.protocol.jar.JarURLConnection.<init>(JarURLConnection.java:61)
at sun.net.www.protocol.jar.Handler.openConnection(Handler.java:24)
at java.net.URL.openConnection(URL.java:943)
at com.sun.crypto.provider.SunJCE_d.run(DashoA6275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.crypto.provider.SunJCE_c.a(DashoA6275)
at com.sun.crypto.provider.SunJCE_c.a(DashoA6275)
at com.sun.crypto.provider.SunJCE_c.a(DashoA6275)
at com.sun.crypto.provider.SunJCE.c(DashoA6275)
at com.sun.crypto.provider.SunJCE.b(DashoA6275)
at com.sun.crypto.provider.SunJCE.a(DashoA6275)
at com.sun.crypto.provider.RSACipher.<init>(DashoA6275)
at sun.reflect.GeneratedConstructorAccessor14.newInstance(Unknown Source
)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:27)
...bla bla bla
Any comments or ideas are most welcome and valueable!
Best reagards
Fredrik
Below is the code
--------------------------------------------------
package smime_encryption_and_signing;
import java.net.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.net.ssl.*;
import java.io.*;
import java.security.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
import java.security.cert.*;
import com.dstc.security.smime.*;
public class SendMailSMIMEApplication extends JFrame implements ActionListener
{
JLabel mailserverjLabel = new JLabel("Mail-server");
JLabel fromjLabel = new JLabel("From");
JLabel tojLabel = new JLabel("To");
JLabel subjectjLabel = new JLabel("Subject");
JLabel messagejLabel = new JLabel("Message");
JTextField mailserverjTextField = new JTextField("mail1.telia.com");
JTextField fromjTextField = new JTextField("fredand44@hotmail.com");
JTextField tojTextField = new JTextField("fredand44@hotmail.com");
JTextField subjectjTextField = new JTextField("A subject");
JTextArea messagejTextArea = new JTextArea("A message!");
JScrollPane jScrollPane = new JScrollPane(messagejTextArea);
JButton jButton = new JButton("Send");
public SendMailSMIMEApplication()
{
setSize(400, 400);
getContentPane().setLayout(null);
setBackground(new Color(200, 200, 200));
mailserverjLabel.setBounds(5, 5, 100, 25);
fromjLabel.setBounds(5, 35, 100, 25);
tojLabel.setBounds(5, 65, 100, 25);
subjectjLabel.setBounds(5, 95, 100, 25);
messagejLabel.setBounds(5, 125, 100, 25);
jButton.setBounds(5, 155, 100, 25);
mailserverjTextField.setBounds(110, 5, 280, 25);
fromjTextField.setBounds(110, 35, 280, 25);
tojTextField.setBounds(110, 65, 280, 25);
subjectjTextField.setBounds(110, 95, 280, 25);
jScrollPane.setBounds(110, 125, 280, 240);
jButton.addActionListener(this);
getContentPane().add(mailserverjLabel);
getContentPane().add(fromjLabel);
getContentPane().add(tojLabel);
getContentPane().add(subjectjLabel);
getContentPane().add(messagejLabel);
getContentPane().add(jButton);
getContentPane().add(mailserverjTextField);
getContentPane().add(fromjTextField);
getContentPane().add(tojTextField);
getContentPane().add(subjectjTextField);
getContentPane().add(jScrollPane);
}
public void actionPerformed(ActionEvent e)
{
String error = sendMail();
if(!error.equals("No errors"))
{
messagejTextArea.setText(error);
}
}
public String sendMail()
{
try
{
Security.insertProviderAt(new com.dstc.security.provider.DSTC(), 2);
Security.addProvider(new com.dstc.security.keymanage.keystore.DSTC());
Properties properties = new Properties();
properties.put("mail.smtp.host", mailserverjTextField.getText());
Session mailSession = Session.getDefaultInstance(properties, null);
//session = Session.getDefaultInstance(System.getProperties(), null);
// certs
X509Certificate recipientCertificate = getCertificate("smime_encryption_and_signing/ReceiverCertificate.cer");
X509Certificate senderCertificate = getCertificate("smime_encryption_and_signing/SenderCertificate.cer");
X509Certificate caCertificate = getCertificate("smime_encryption_and_signing/thawte_certificate.cer");
PrivateKey senderKey = getPrivateKey("smime_encryption_and_signing/smime_keystore", "sender_keypair", "password".toCharArray());
InternetAddress fromAddress = new InternetAddress(fromjTextField.getText());
MimeMessage mimeMessage = new MimeMessage(mailSession);
mimeMessage.setFrom(fromAddress);
InternetAddress internetAddress = new InternetAddress(tojTextField.getText());
mimeMessage.setRecipient(Message.RecipientType.TO, internetAddress);
mimeMessage.setSentDate(new java.util.Date());
mimeMessage.setSubject(subjectjTextField.getText());
mimeMessage.setText(messagejTextArea.getText());
X509Certificate[] senderCertificates = {senderCertificate, caCertificate};
mimeMessage = signMimeMessage(mimeMessage, senderKey, senderCertificates);
X509Certificate[] recipientCertificates = { recipientCertificate };
mimeMessage = encryptMimeMessage(mimeMessage, recipientCertificates);
Transport.send(mimeMessage);
System.out.println("Message sent");
return "No errors";
}
catch(Exception e)
{
e.printStackTrace();
return e.getMessage();
}
}
public X509Certificate getCertificate(String certificateFile)
{
try
{
FileInputStream fileInputStream = new FileInputStream(certificateFile);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
byte[] certificateData = new byte[fileInputStream.available()];
dataInputStream.readFully(certificateData);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(certificateData);
CertificateFactory fact = CertificateFactory.getInstance("X509");
X509Certificate certificate = (X509Certificate) fact.generateCertificate(byteArrayInputStream);
return certificate;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
public PrivateKey getPrivateKey(String keystoreFile, String alias, char[] password)
{
try
{
FileInputStream fileInputStream = new FileInputStream(keystoreFile);
KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(fileInputStream, password);
return (PrivateKey) keyStore.getKey(alias, password);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
public MimeMessage signMimeMessage(MimeMessage mimeMessage, PrivateKey privateKey, X509Certificate[] certificates)
{
try
{
SMIMESignature smimeSignature = new SMIMESignature();
smimeSignature.initSign("SHA-1", privateKey, certificates, false);
smimeSignature.setMessage(mimeMessage);
return smimeSignature.sign();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public MimeMessage encryptMimeMessage(MimeMessage mimeMessage, X509Certificate[] certificates)
{
try
{
SMIMECipher smimeCipher = new SMIMECipher();
smimeCipher.initEncrypt(new SecureRandom(), "DESede", certificates);
smimeCipher.setMessage(mimeMessage);
return smimeCipher.encrypt();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
SendMailSMIMEApplication sendMailSMIMEApplication = new SendMailSMIMEApplication();
sendMailSMIMEApplication.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sendMailSMIMEApplication.setVisible(true);
}
}
