本文介绍了Java:将DKIM私钥从RSA转换为JavaMail的DER的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我正在使用 DKIM for JavaMail 使用DKIM签署外发邮件.
我的私人DKIM密钥是用opendkim-genkey -s default -d example.com生成的,看起来像这样:

I'm using DKIM for JavaMail to sign outgoing mail with DKIM.
My private DKIM key is generated with opendkim-genkey -s default -d example.com and looks like this:

-----BEGIN RSA PRIVATE KEY-----
ABCCXQ...[long string]...SdQaZw9
-----END RSA PRIVATE KEY-----

用于JavaMail的DKIM库需要如其自述文件所述的DER格式的私有DKIM密钥:

The DKIM for JavaMail library needs the private DKIM key in DER format as stated in their readme file:

openssl pkcs8 -topk8 -nocrypt -in private.key.pem -out private.key.der -outform der

我正在寻找一种避免必须使用openssl将密钥转换为DER格式的方法.相反,我想直接在Java中进行转换.
我尝试了不同的建议(1 2 ,),但到目前为止没有任何效果.
DKIM for Java会像下面这样处理DER文件:

I am looking for a way to avoid having to use openssl to convert my key to DER format. Instead I would like to do the conversion in Java directly.
I have tried different suggestions (1, 2, 3) but nothing has worked so far.
DKIM for Java processes the DER file like this:

    File privKeyFile = new File(privkeyFilename);

    // read private key DER file
    DataInputStream dis = new DataInputStream(new FileInputStream(privKeyFile));
    byte[] privKeyBytes = new byte[(int) privKeyFile.length()];
    dis.read(privKeyBytes);
    dis.close();

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");

    // decode private key
    PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privKeyBytes);
    RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);

所以最后我需要的是RSAPrivateKey.

So in the end what I need is the RSAPrivateKey.

如何从我的RSA私钥轻松生成DKIM for JavaMail所需的RSAPrivateKey?

How can I easily generate this RSAPrivateKey that DKIM for JavaMail requires from my RSA private key?

推荐答案

您的参考文献3(仅)是正确的;因为它说您的问题不只是转换PEM到DER(如@Jim所说的基本上只是base64到二进制),但可以转换包含openssl传统"或旧版"或"PKCS#1"格式密钥数据的PEM包含PKCS#8(特别是PKCS#8清除/未加密)格式密钥数据的DER.

Your reference 3 (only) is correct; as it says your problem is not just convertingPEM to DER (which as @Jim says is basically just base64 to binary) but convertingPEM containing openssl "traditional" or "legacy" or "PKCS#1" format key data toDER containing PKCS#8 (and specifically PKCS#8 clear/unencrypted) format key data.

http://juliusdavies.ca/commons-ssl/pkcs8.html 由Alistair的答案指出似乎有可能,但我没有详细检查.从PKCS#8开始RSA的clear(PrivateKeyInfo)只是PKCS#1周围的一个简单ASN.1包装器,以下(有点)快速和(非常)肮脏的代码提供了一个最小的解决方案.更改输入读取逻辑(和错误处理)以尝试并替换可用的base64解码器.

The http://juliusdavies.ca/commons-ssl/pkcs8.html pointed to by Alistair's answerlooks like it might be a possibility, but I didn't examine in detail. Since PKCS#8clear (PrivateKeyInfo) for RSA is just a simple ASN.1 wrapper around the PKCS#1,the following (kinda) quick and (very) dirty code provides a minimal solution.Alter the input-reading logic (and error handling) to taste and substitute an available base64 decoder.

    BufferedReader br = new BufferedReader (new FileReader (oldpem_file));
    StringBuilder b64 = null;
    String line;
    while( (line = br.readLine()) != null )
        if( line.equals("-----BEGIN RSA PRIVATE KEY-----") )
            b64 = new StringBuilder ();
        else if( line.equals("-----END RSA PRIVATE KEY-----" ) )
            break;
        else if( b64 != null ) b64.append(line);
    br.close();
    if( b64 == null || line == null )
        throw new Exception ("didn't find RSA PRIVATE KEY block in input");

    // b64 now contains the base64 "body" of the PEM-PKCS#1 file
    byte[] oldder = Base64.decode (b64.toString().toCharArray());

    // concatenate the mostly-fixed prefix plus the PKCS#1 data
    final byte[] prefix = {0x30,(byte)0x82,0,0, 2,1,0, // SEQUENCE(lenTBD) and version INTEGER
            0x30,0x0d, 6,9,0x2a,(byte)0x86,0x48,(byte)0x86,(byte)0xf7,0x0d,1,1,1, 5,0, // AlgID for rsaEncryption,NULL
            4,(byte)0x82,0,0 }; // OCTETSTRING(lenTBD)
    byte[] newder = new byte [prefix.length + oldder.length];
    System.arraycopy (prefix,0, newder,0, prefix.length);
    System.arraycopy (oldder,0, newder,prefix.length, oldder.length);
    // and patch the (variable) lengths to be correct
    int len = oldder.length, loc = prefix.length-2;
    newder[loc] = (byte)(len>>8); newder[loc+1] = (byte)len;
    len = newder.length-4; loc = 2;
    newder[loc] = (byte)(len>>8); newder[loc+1] = (byte)len;

    FileOutputStream fo = new FileOutputStream (newder_file);
    fo.write (newder); fo.close();
    System.out.println ("converted length " + newder.length);

此外:我认为您发布的数据中的ABCC已被删除.任何有效和合理的PKCS#1(清除)RSA密钥必须以字节0x30 0x82 x开头,其中x从2到大约9;当转换为base64时,必须以MIIC到MIIJ开头.

Aside: I assume the ABCC in your posted data was redacted. Any valid and reasonablePKCS#1 (clear) RSA key must begin with bytes 0x30 0x82 x where x is from 2 to about 9;when converted to base64 this must begin with MIIC to MIIJ.

这篇关于Java:将DKIM私钥从RSA转换为JavaMail的DER的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-08 01:49