?
Solved

java DKIM Implementation?

Posted on 2008-11-17
23
Medium Priority
?
1,042 Views
Last Modified: 2012-05-05
Hello,
Does anyone out there know of a java class that is available that will take an email message (text format), and a key, and generate a DKIM signature out of it? We're trying to implement DKIM on our homebrew mail server, and dont really want to recreate the wheel if we can avoid it.

Thanks,
Rick
0
Comment
Question by:richardsimnett
  • 12
  • 11
23 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 22983469
Not sure there's a Java implementation
0
 

Author Comment

by:richardsimnett
ID: 22988763
CEHJ,
I found this:

http://www.badpenguin.co.uk/dkim/

Seems promising, however, I dont get one thing. The class Signer takes a PrivateKey, which is a java security interface. How do I convert a string (containing the key) to a PrivateKey for usage with the DKIM interfaces provided?

Thanks,
Rick
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22988858
Well let me ask a question first: why would you have a proper key (part of a key pair) in String format?
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:richardsimnett
ID: 22988981
well because the key would be stored locally in the mail server config file for quick referencing. Then before the message is sent over the specified virtual server (and domain) the key would be retrieved, the message signed, and the sent in the DATA portion of the SMTP transaction.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22989060
Well, firstly, a key can't be represented as a String without some form of transformative encoding, such as Base64 and secondly, it would be poor security to store it outside a keystore. At a pinch, it might be cached in memory, but not as a String
0
 

Author Comment

by:richardsimnett
ID: 22989081
ok so how would u do it?
0
 

Author Comment

by:richardsimnett
ID: 22989111
Storing as base64 isnt difficult at all. But if there is a better way to do it, im interesting in hearing it.
0
 

Author Comment

by:richardsimnett
ID: 22989270
actually, let me restate the problem. maybe my understanding is totally wrong here.

Basically what Im not sure of how to do is this. Generate a key-pair usable by the dkim implementation, how to configure it for usage, and finally how to load the key into my java app to sign emails with the key using the Signer.

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22989603
The following works for me:
import badpenguin.dkim.test.KeyManager;
import java.io.*;
 
public class KeyTest {
 
    public static void main(String[] args) throws Exception {
        String keystoreFile = args[0];
        String keypass = args[1];
        KeyManager km = new KeyManager(new FileInputStream(keystoreFile), keypass);
        // Get key with alias 'business'
        System.out.println(km.getKey("business"));
    }
}

Open in new window

0
 

Author Comment

by:richardsimnett
ID: 22989892
Ok that wont work for our software, what we need to do is generate public / private keys using ssl, post the public key to DNS, and have the private key posted to a configuration form in our mailing software like this:

-----BEGIN RSA PRIVATE KEY-----
MIGrAgEAAiEAyGPkxyrEasNyDai7wdDHasNUMG5TO8YQ8fA2pr2UcA8CAwEAAQIg
MOOWLDU16Go4iDaTYCzEicvOGxLHOfElTtWdozp5KsECEQDx6bGknhmaajE2OAJU
dGEvAhEA1A8z04R7AneRl2MpbaZnIQIRANSWAT4gkW9ZEpYK8kE1ZJECEDmbA54i
7/OEnaU9R8TEnmECEQDSZDw1ia2+osfbyZ67OJ/n
-----END RSA PRIVATE KEY-----


somehow, I have to get that translated into a key usable by the DKIM implementation.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22989974
>>Ok that wont work for our software

Why not - my example uses the Java keystore?
0
 

Author Comment

by:richardsimnett
ID: 22990529
our users arent very technical. Creating a keystore and what not is more than we want them to have to do. Using openssl its simple for us to create keys for them via a script, and have them copy and paste the key into a web browser for configuration.

We have to take a base64 encoded string like the one above, have it submitted via the webform, the webform stores it to their configuration data in our db, and their server retrieves the updated configuration. It has to be done with Strings.

So the question remains how to get base64 encoded string, and convert to a private key.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22990973
These crypto classes are nightmarishly tricky to use. I've been having a go at this but there are still some problems. I'll post what i've done so far. You can probably tell i don't know what i'm doing on the last line, but that's academic in fact as it's blowing up over the dkim key i'm trying to import
import java.io.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.PrivateKey;
import java.security.KeyFactory;
import badpenguin.dkim.Signer;
 
 
public class TestKey2 {
    public static void main(String[] args) throws Exception {
        File privKeyFile = new File(args[0]);
        byte[] keyBytes = new byte[(int)privKeyFile.length()];
        DataInputStream in = new DataInputStream(new FileInputStream(privKeyFile));
        in.readFully(keyBytes);
        PKCS8EncodedKeySpec pks = new PKCS8EncodedKeySpec(keyBytes);
        //System.out.println(pk);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey pk = kf.generatePrivate(pks);
        Signer s = new Signer("X", "technojeeves.com", "From", "rsa-sha256", pk);
    }
}

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22991010
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 2000 total points
ID: 22991118
I've done it (for DER format):
import java.io.*;
import java.security.spec.PKCS8EncodedKeySpec;
import org.apache.commons.ssl.PKCS8Key;
import java.security.PrivateKey;
import java.security.KeyFactory;
import badpenguin.dkim.Signer;
 
 
public class TestKey2 {
    public static void main(String[] args) throws Exception {
        File privKeyFile = new File(args[0]);
        byte[] keyBytes = new byte[(int)privKeyFile.length()];
        DataInputStream in = new DataInputStream(new FileInputStream(privKeyFile));
        in.readFully(keyBytes);
        PKCS8Key pks = new PKCS8Key(keyBytes, null);
        Signer s = new Signer("X", "technojeeves.com", "From", "rsa-sha256", pks.getPrivateKey());
        String signedMail = s.signMail(new FileInputStream("testmail.eml"));
        System.out.println(signedMail);
    }
}

Open in new window

0
 

Author Comment

by:richardsimnett
ID: 22991781
ok I will have to review the code in the morning to see if I can get it to work with what I have already written, this is a very small class I began working on that I thought would work, but doesnt (throws exception errors).

import sun.misc.BASE64Decoder;
import sun.security.pkcs.PKCS8Key;
import java.security.*;
import java.io.*;

/**
 *
 * @author rick
 */
public class domainKey {
    PKCS8Key pk = null;
   
    void initializePrivateKey(String key)
    {
        if (key.length() > 0)
        {
            System.out.println("Initializing Private Key: " + key);
            pk = new PKCS8Key();
       
            try
            {
                pk.decode(new BASE64Decoder().decodeBuffer(key));
            }
            catch(IOException ie)
            {
                System.out.println("IOError initializing key: " + ie.getMessage());
            }
            catch(InvalidKeyException ike)
            {
                System.out.println("Error Initializing Key: " + ike.getMessage());
            }
        }
    }

When I feed it the following I get these errors:

Initializing Private Key: MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMhj5McqxGrDcg2ou8HQx2rDVDBuUzvGEPHwNqa9lHAPAgMBAAE=
Error Initializing Key: IOException : DER input, Integer tag error

This is with the rsa.public key generated via the openssl instructions you mentioned above. I tried it with the rsa.private key it generated, but I got a totally different error.

Initializing Private Key: MIGrAgEAAiEAyGPkxyrEasNyDai7wdDHasNUMG5TO8YQ8fA2pr2UcA8CAwEAAQIgMOOWLDU16Go4iDaTYCzEicvOGxLHOfElTtWdozp5KsECEQDx6bGknhmaajE2OAJUdGEvAhEA1A8z04R7AneRl2MpbaZnIQIRANSWAT4gkW9ZEpYK8kE1ZJECEDmbA54i7/OEnaU9R8TEnmECEQDSZDw1ia2+osfbyZ67OJ/n
Error Initializing Key: IOException : algid parse error, not a sequence

Anyways.. Any feedback is appreciated, I will start looking into the code you provided above in the AM.

Thanks,
Rick
0
 

Author Comment

by:richardsimnett
ID: 22992068
Question. If the code above does it for DER, how do you get it to do it in PEM (whcih is what the key generated by the info site has us generate).
0
 

Author Comment

by:richardsimnett
ID: 22992105
cehj,
Also tried it using your org.apache.commons.ssl package... still doesnt seem to work right.. I get here is the code:

import org.apache.commons.ssl.*;
import java.security.*;
//import java.io.*;

/**
 *
 * @author rick
 */
public class domain {
    int uribl = 0;
    int surbl = 0;
    PrivateKey pk = null;
   
    void initializePrivateKey(String key)
    {
        if (key.length() > 0)
        {
            System.out.println("Initializing Private Key: " + key);
           
            try
            {
                PKCS8Key pkcs8 = new PKCS8Key(key.getBytes(), null );
                     
                pk = pkcs8.getPrivateKey();
            }
            catch(java.security.GeneralSecurityException gse)
            {
                System.out.println("GSE: " + gse.getLocalizedMessage());
            }
        }
    }
}
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22992566
Unfortunately Rick, this has taken up a disproportionate amount of time for me, though you're welcome to contact me through my profile to see if we can come to some arrangement on this.
0
 

Author Closing Comment

by:richardsimnett
ID: 31517758
Thanks for the help!
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22997811
Good luck with that - interesting stuff!
0
 

Author Comment

by:richardsimnett
ID: 22997890
Thanks,
I actually have it working up til it calls the signMail() function. At that point, I get an exception from within the dkim package itself, a string -1 error, somewhere in the canonicaliser.java. I am in contact with the developer, and will see what he has to say. I may be contacting you in the near future, to further discuss a solution (if this doesnt work out).
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 22998084
OK. signMail worked for me, but then it was an artificially simple example
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Suggested Courses
Course of the Month13 days, 19 hours left to enroll

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question