gpt4 book ai didi

java - 使用 BouncyCaSTLe 从 PEM 格式恢复 EC 私钥

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:27:32 24 4
gpt4 key购买 nike

我的应用程序以 PEM 格式存储私钥,现有代码适用于 RSA key ,但我正在尝试切换到 EC key ,但出现问题。 key 恢复似乎有效,恢复 key 上的 equals 方法对原始 key 返回 true,但原始 key 上的 getAlgorithm() 返回“EC”,恢复 key 上返回“ECDSA”。算法中的差异后来会导致问题,因为它与相应公钥的算法不匹配。

我做错了什么还是 PEM 解析器中的错误?

这是一个演示问题的测试程序:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;

import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.immutify.janus.keytool.KeyToolUtils;

public class TestPrivateKeyRecovery
{
private static final String KEY_ALGORITHM = "EC";
private static final String SIGNATURE_ALGORITHM = "SHA512withECDSA";
private static final String PROVIDER = "BC";
private static final String CURVE_NAME = "secp521r1";
private static final String WRAPPING_CIPHER_SPEC = "ECIESwithAES";

private ECGenParameterSpec ecGenSpec;
private KeyPairGenerator keyGen_;
private SecureRandom rand_;

public void run()
{
try
{
rand_ = new SecureRandom();
ecGenSpec = new ECGenParameterSpec(CURVE_NAME);
keyGen_ = KeyPairGenerator.getInstance(KEY_ALGORITHM, PROVIDER);

keyGen_.initialize(ecGenSpec, rand_);


PrivateKey privateKey = keyGen_.generateKeyPair().getPrivate();





String der = privateKeyToDER(privateKey);

PrivateKey recoveredKey = privateKeyFromDER(der);

System.out.println("privateKey=" + privateKey);
System.out.println("privateKey.getAlgorithm()=" + privateKey.getAlgorithm());
System.out.println("der=" + der);
System.out.println("recoveredKey=" + privateKey);
System.out.println("recoveredKey.getAlgorithm()=" + recoveredKey.getAlgorithm());
System.out.println();

if(privateKey.equals(recoveredKey))
System.out.println("Key recovery ok");
else
System.err.println("Private key recovery failed");

if(privateKey.getAlgorithm().equals(recoveredKey.getAlgorithm()))
System.out.println("Key algorithm ok");
else
System.err.println("Key algorithms do not match");
}
catch(Exception e)
{
e.printStackTrace();
}
}

public static String privateKeyToDER(PrivateKey key) throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PEMWriter pemWriter = new PEMWriter(new OutputStreamWriter(bos));

pemWriter.writeObject(key);

pemWriter.close();

return new String(bos.toByteArray());
}

public static PrivateKey privateKeyFromDER(String der) throws IOException
{
StringReader reader = new StringReader(der);
PEMParser pemParser = new PEMParser(reader);

try
{
Object o = pemParser.readObject();

if (o == null || !(o instanceof PEMKeyPair))
{
throw new IOException("Not an OpenSSL key");
}

KeyPair kp = new JcaPEMKeyConverter().setProvider("BC").getKeyPair((PEMKeyPair)o);
return kp.getPrivate();
}
finally
{
pemParser.close();
}
}
}

测试程序的输出是:

privateKey=EC Private Key             S: 13d19928468d14fabb9235a81fc1ec706ff5413a70a760b63e07d45a5d04a2f18425ef735500190291aacaf58c92306acd87fa01a47d907d5d3fc01531180353146privateKey.getAlgorithm()=ECder=-----BEGIN EC PRIVATE KEY-----MIHcAgEBBEIBPRmShGjRT6u5I1qB/B7HBv9UE6cKdgtj4H1FpdBKLxhCXvc1UAGQKRqsr1jJIwas2H+gGkfZB9XT/AFTEYA1MUagBwYFK4EEACOhgYkDgYYABAFN5ZcEzg9fV13u57ffwyN9bm9Wa9Pe0MtL2cd5CW2ku4mWzgS5m8IfNMAw2QMah5Z9fuXW1fGJgUx1RsC09R6legFTgymlbqt+CaPhNsJkr12cjyzhT1NxR6uEzMUtBcYxqLHyANkhHmvAk221//YIRIWix7ZlRsRrs+iYrpWw4bMt9A==-----END EC PRIVATE KEY-----recoveredKey=EC Private Key             S: 13d19928468d14fabb9235a81fc1ec706ff5413a70a760b63e07d45a5d04a2f18425ef735500190291aacaf58c92306acd87fa01a47d907d5d3fc01531180353146recoveredKey.getAlgorithm()=ECDSAKey recovery okKey algorithms do not match

最佳答案

问题不在于PEMParser,而在于JcaPEMKeyConverter,它将EC key 视为ECDSA 的 key :

algorithms.put(X9ObjectIdentifiers.id_ecPublicKey, "ECDSA");
...
private KeyFactory getKeyFactory(AlgorithmIdentifier algId)
throws NoSuchAlgorithmException, NoSuchProviderException
{
ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
String algName = (String)algorithms.get(algorithm);
...

算法标识符是 id-ecPublicKey,它也用于 ECDSA key ,因此这里的算法选择不是唯一的,可能 BC 开发人员选择了 ECDSA 作为最合适的选择。您可以使用自己的 KeyFactory 执行类似 JcaPEMKeyConverter 的操作,但要为 EC key 选择正确的算法。

关于java - 使用 BouncyCaSTLe 从 PEM 格式恢复 EC 私钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27743045/

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