当前位置: 首页 > 知识库问答 >
问题:

Java:将DKIM私钥从RSA转换为用于JavaMail的DER

宣冥夜
2023-03-14

我正在使用DKIM for JavaMail来用DKIM对发送的邮件进行签名
我的私有DKIM密钥是通过opendkim genkey-s default-d示例生成的。com,看起来像这样:

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

DKIM for JavaMail库需要DER格式的专用DKIM密钥,如自述文件所述:

DKIM for JavaMail需要DER格式的私钥,您可以使用openssl转换PEM密钥:

openssl pkcs8-topk8-nocrypt-in private。钥匙pem-out private。钥匙der-从der中取出

我正在寻找一种方法来避免使用openssl将我的密钥转换为DER格式。相反,我想直接在Java中进行转换。
我尝试了不同的建议(1,2,3),但到目前为止没有任何效果。
Java的DKIM处理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所需的RSAPrivate ateKey?

共有2个答案

程修雅
2023-03-14

PEM格式只是Base64中编码的DER字节。您可以将PEM文件读取为文本文件,并且只取 "-----BEGIN RSA PRIVATE KEY-----" 和 "-----END RSA PRIVATE KEY之间的行-----".

PEM文件中允许注释,因此您可能需要从开始跳过其他行,直到您到达 "-----BEGIN RSA PRIVATE KEY-----".

下面是Ruby中的一些代码,只需对文本进行Base64解码,即可将PEM转换为DER。您可以将其转换为Java:

require 'base64'

# Read the PEM as text
pem = File.read('key.pem')

# Break into individual lines
all_lines = pem.split("\n")

# Discard the first and last lines
b64_lines = all_lines[1..-2]

# Write the output file
File.open('key.der', 'w') do |f|
    # For each line
    b64_lines.each do |line|
        # Write the Base64-decoded bytes
        f.write Base64.decode64(line)
    end
end

下面是openssl,它显示了我刚刚创建的RSA密钥:

$ openssl rsa -text -in key.pem
Private-Key: (2048 bit)
modulus:
    00:aa:8d:15:05:db:a3:fa:bb:dc:8d:4f:d5:53:56:
    d6:78:7f:41:6d:05:b9:92:a4:7c:28:b1:11:50:9e:
    77:67:04:e9:77:22:62:db:1f:43:bc:f2:5e:fc:f3:
    42:35:a2:01:9c:9c:c1:90:b7:2b:1c:c8:51:f2:27:
... (omitted)

这里是openssl显示Ruby代码编写的DER文件:

$ openssl rsa -text -inform DER -in key.der
Private-Key: (2048 bit)
modulus:
    00:aa:8d:15:05:db:a3:fa:bb:dc:8d:4f:d5:53:56:
    d6:78:7f:41:6d:05:b9:92:a4:7c:28:b1:11:50:9e:
    77:67:04:e9:77:22:62:db:1f:43:bc:f2:5e:fc:f3:
    42:35:a2:01:9c:9c:c1:90:b7:2b:1c:c8:51:f2:27:
...

这就是PEM(中间部分省略):

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqo0VBduj+rvcjU/VU1bWeH9BbQW5kqR8KLERUJ53ZwTpdyJi
2x9DvPJe/PNCNaIBnJzBkLcrHMhR8ici2aOpuPZi/EDxjRcNPF1Bj+ULvYNLMEDb
2ng9HhyyQtZMllYpkuewONSsTfrsOKEm3NXFfjAclVAGUHp6JpBCTfd32VbHGmJl
...
S4SwxwUV39H2Zq+X1pSIEssSUduyGvF7jJadHe5OiacD5112bkF+Tx/YThMcMebg
8IrO8DyBIBfgAcQPq2GSY99ImacZ++OLXcXdC9NYZ3U9T2SCJdf5
-----END RSA PRIVATE KEY-----
薛焱
2023-03-14

你的参考文献3(仅)是正确的;正如它所说的,您的问题不仅仅是将PEM转换为DER(正如@Jim所说,基本上只是将base64转换为二进制),而是将包含openssl“传统”或“遗留”或“PKCS#1”格式密钥数据的PEM转换为包含PKCS#8(特别是PKCS#8清除/未加密)格式密钥数据的DER。

这个http://juliusdavies.ca/commons-ssl/pkcs8.html阿利斯泰尔的回答指出,这似乎是一种可能性,但我没有详细研究。因为PKCS#8 clear(PrivateKeyInfo)for RSA只是一个简单的ASN。1围绕PKCS#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 for JavaMail与DKIM签署外发邮件。 我的私人DKIM密钥是使用生成的,如下所示: DKIM for JavaMail库需要DER格式的私有DKIM密钥,如其自述文件所述: DKIM for JavaMail需要DER格式的私钥,您可以使用openssl转换PEM密钥: 我正在寻找一种避免必须使用openssl将密钥转换为DER格式的方法。相反,我想直接

  • 让我先解释一下我的问题。我从CA购买了一个证书,并使用以下格式生成csr和私钥: 有趣的是,在aws文档页面上,他们显示的示例私钥以“------开始RSA私钥-------”开头 有没有办法使用OpenSSL将我的私钥转换为RSA私钥?

  • 我有一个OpenSSH格式的私钥文件: 但我需要RSA格式: 在终端我会这样做: 但我需要用Java来做。 我尝试使用org.bouncycastle.openssl.PEMWriter,但我无法解决如何将我的输入键(作为输入字符串)转换为可传递给PEMWriter的Private ateKey对象。

  • 在Android中,我使用下面的代码将String转换为RSA私钥 https://www.devglan.com/online-tools/rsa-encryption-decryption 但是,当我使用这个网站时,我的代码不起作用。 https://8gwifi.org/RSAFunctionality?keysize=1024 我在Android studio中的代码是: 与第二个链接错误

  • 我需要用java生成openssh格式的密钥对。 我使用java中的KeyPairGenerator生成了一个公私密钥对,并将其保存到一个文件中: 但是,如果我尝试使用这个与ssh-keygen我得到一个"失败加载密钥private.key:无效格式" 如何将PKCS#8私钥转换为openssh格式或生成openssh格式的密钥对?

  • 这是我生成RSA密钥的代码 现在我想转换DER/ASN.1编码字节,也知道使用Java JCE API生成RSA密钥时使用的默认编码格式是什么。