java DKIM Implementation?

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
richardsimnettAsked:
Who is Participating?
 
CEHJCommented:
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
 
CEHJCommented:
Not sure there's a Java implementation
0
 
richardsimnettAuthor Commented:
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
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
CEHJCommented:
Well let me ask a question first: why would you have a proper key (part of a key pair) in String format?
0
 
richardsimnettAuthor Commented:
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
 
CEHJCommented:
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
 
richardsimnettAuthor Commented:
ok so how would u do it?
0
 
richardsimnettAuthor Commented:
Storing as base64 isnt difficult at all. But if there is a better way to do it, im interesting in hearing it.
0
 
richardsimnettAuthor Commented:
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
 
CEHJCommented:
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
 
richardsimnettAuthor Commented:
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
 
CEHJCommented:
>>Ok that wont work for our software

Why not - my example uses the Java keystore?
0
 
richardsimnettAuthor Commented:
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
 
CEHJCommented:
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
 
CEHJCommented:
0
 
richardsimnettAuthor Commented:
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
 
richardsimnettAuthor Commented:
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
 
richardsimnettAuthor Commented:
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
 
CEHJCommented:
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
 
richardsimnettAuthor Commented:
Thanks for the help!
0
 
CEHJCommented:
Good luck with that - interesting stuff!
0
 
richardsimnettAuthor Commented:
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
 
CEHJCommented:
OK. signMail worked for me, but then it was an artificially simple example
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.