ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java:将DKIM私钥从RSA转换为DER for JavaMail

2019-09-28 03:02:29  阅读:350  来源: 互联网

标签:dkim java javamail


我正在使用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 needs the private key in DER format, you can
transform a PEM key
with 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到二进制)但转换
PEM包含openssl“传统”或“遗留”或“PKCS#1”格式的密钥数据
DER包含PKCS#8(特别是PKCS#8清除/未加密)格式的密钥数据.

阿利斯泰尔的回答指出了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开始.

标签:dkim,java,javamail
来源: https://codeday.me/bug/20190928/1825593.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有