我正在使用DKIM for JavaMail与DKIM签署外发邮件。
我的私人DKIM密钥是用opendkim-genkey -s default -d example.com
生成的,看起来像这样:
-----BEGIN RSA PRIVATE KEY-----
ABCCXQ...[long string]...SdQaZw9
-----END RSA PRIVATE KEY-----
DKIM for JavaMail库需要DER格式的私有DKIM密钥,如其自述文件所述:
DKIM for JavaMail需要DER格式的私钥,您可以
转换PEM密钥
使用openssl:
openssl pkcs8 -topk8 -nocrypt -in private.key.pem -out private.key.der -outform der
我正在寻找一种避免必须使用openssl将密钥转换为DER格式的方法。相反,我想直接在Java中进行转换。
我尝试了不同的建议(1,2,3),但到目前为止没有任何效果。
DKIM for Java如下处理DER文件:
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
。如何从RSA私钥轻松生成DKIM for JavaMail所需的
RSAPrivateKey
? 最佳答案
您的参考文献3(仅)是正确的;因为它说您的问题不只是转换
PEM到DER(@Jim所说的基本上只是base64到二进制文件),但可以转换
包含openssl“传统”或“旧版”或“ PKCS#1”格式密钥数据的PEM
包含PKCS#8(特别是PKCS#8清除/未加密)格式密钥数据的DER。
Alistair的答案所指向的http://juliusdavies.ca/commons-ssl/pkcs8.html
似乎有可能,但我没有详细检查。从PKCS#8开始
RSA的clear(PrivateKeyInfo)只是PKCS#1周围的一个简单ASN.1包装器,
以下(有点)快速和(非常)肮脏的代码提供了最小的解决方案。
更改输入读取逻辑(和错误处理)以尝试并替换可用的base64解码器。
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开头。
关于java - Java:将DKIM私钥从RSA转换为JavaMail的DER,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23709898/