gpt4 book ai didi

java - 使用java生成openssl key 对

转载 作者:行者123 更新时间:2023-12-04 10:14:24 33 4
gpt4 key购买 nike

我需要在 java 中生成 openssl key 对来模拟以下内容:

openssl ecparam -name prime256v1 -genkey -noout -out prime256v1.key

openssl pkcs8 -topk8 -in prime256v1.key -out prime256v1-priv.pem -nocrypt

openssl ec -in prime256v1-priv.pem -pubout -out prime256v1-pub.pem

我的java程序如下:
public static void main(String args[]) throws Exception{

Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
ECGenParameterSpec spec = new ECGenParameterSpec("secp256r1");
g.initialize(spec);
KeyPair keyPair = g.generateKeyPair();

byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
String publicKeyContent = Base64.encode(publicKeyBytes);
String publicKeyFormatted = "-----BEGIN PUBLIC KEY-----" + System.lineSeparator();
for (final String row:
Splitter
.fixedLength(64)
.split(publicKeyContent)
)
{
publicKeyFormatted += row + System.lineSeparator();
}
publicKeyFormatted += "-----END PUBLIC KEY-----";
BufferedWriter writer = new BufferedWriter(new FileWriter("publickey.pem"));
writer.write(publicKeyFormatted);
writer.close();

byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
String privateKeyContent = Base64.encode(privateKeyBytes);
String privateKeyFormatted = "-----BEGIN PRIVATE KEY-----" + System.lineSeparator();
for (final String row:
Splitter
.fixedLength(64)
.split(privateKeyContent)
)
{
privateKeyFormatted += row + System.lineSeparator();
}
privateKeyFormatted += "-----END PRIVATE KEY-----";
BufferedWriter writer2 = new BufferedWriter(new FileWriter("privatekey.pem"));
writer2.write(privateKeyFormatted);
writer2.close();
}

上面的代码有效,但生成的私钥似乎比我在顶部提到的命令行实用程序生成的要长。

带命令行的私钥:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGuyf3+/6+rnDKw0D
WbxVyggwNL0jlTVAzGm6cpl3ji2hRANCAAQ7zLtxLLvl6LJHJAlYAZr4hAc09fZn
bAniYIeKVqVBdKIvb5R445PFiUDFcfyneeX/resPXJHMEm/vAxfQeMqL
-----END PRIVATE KEY-----

带有java的私钥:
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgYFPrkmxnwjVBgpUV
B02/luLD1rt9
UWZHj62YdhwYQESgCgYIKoZIzj0DAQehRANCAATZp7Jl8KXXApA
hvv9qeQtX5LbHQkrCdx3DfkUC
GgCUMSJWKxs7yJPNKtFZnFUTFZfyEF76fdEzky
zIon5H04MX
-----END PRIVATE KEY-----

即使我在这里删除了 2 条额外的行,即便如此,这似乎也是一个更大的关键。

带命令行的公钥:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEO8y7cSy75eiyRyQJWAGa+IQHNPX2
Z2wJ4mCHilalQXSiL2+UeOOTxYlAxXH8p3nl/63rD1yRzBJv7wMX0HjKiw==
-----END PUBLIC KEY-----

Java 公钥:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2aeyZfCl1wKQIb7/ankLV+S2x0JK
wncdw35FAhoA
lDEiVisbO8iTzSrRWZxVExWX8hBe+n3RM5MsyKJ+R9ODFw==
-----END PUBLIC KEY-----

所以,我的第一个问题是关于私钥长度的。好像更长了。
我的第二个问题是我似乎没有正确拆分生成的 key 字节。肯定有比预期更多的线路。如何纠正?

最佳答案

... the private key length ... seems longer



它是,或者准确地说,表示/包含私钥的结构更长。 Java 包括 PKCS8 中的可选 -- 和不必要的(冗余) -- '参数' 特定算法数据的字段,即 SEC1 appendix C.4 中定义的 ECPrivateKey ,而 OpenSSL 没有。这将在读回时被忽略。两个结构中的实际键值是正确的大小。

I am not splitting the generated key bytes properly



相反,拆分对( key 结构的)字节进行编码的(base64)字符。

查看 Base64.encode 的输出之前 Splitter .我敢打赌,您会发现它在每 76 个 base64 字符之后已经包含换行符,这与某些人认为更常见(或更重要?)或至少比 PEM 更新的 MIME 标准(RFC 1521 et seq)一致。 (尽管 XML 和 JWX 甚至更新并且现在很常见,并且根本不插入换行符。)因此您的 Splitter需要:
  • 第一行的前 64 个字符
  • 第一行的剩余 12 个字符、换行符和第二行的 51 个字符
  • 第二行的剩余 25 个字符、换行符和(最多)第三行的 38 个字符

  • 尽管 OpenSSL 每 64 个字符(最后一行除外)写入带有正文换行符的 PEM 文件,但根据 PEM 标准 (RFC 1421),它始终能够读取 4 到 76 个字符的任意倍数的文件,与 MIME 一致。自 2016 年 1.1.0 以来的最新版本,现已被广泛采用,可以读取多达数百个字符的行。因此,如果您的文件要由(任何使用)OpenSSL 库读取,您可以只编写 split-at-76 版本而无需任何进一步更改,除非确保有一个换行符终止最后一行。其他软件可能有所不同;如果您需要安全或严格合规,请首先从您的 Base64.encode 中删除换行符。输出,然后以正确的 64 间距将它们添加回来。参见 the recently published respecification .

    PS:如果您使用 Java 将此 key 放在 PKCS12 keystore 中(这需要您拥有/获取/为其创建证书),openssl 命令行可以直接读取,并将(1)私钥转换为 PEM,(2)证书到 PEM,您可以从中提取 PEM 中的公钥。

    关于java - 使用java生成openssl key 对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61145701/

    33 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com