gpt4 book ai didi

java - 从未压缩的客户端临时公钥和 Open SSL 静态服务器私钥生成 ECPublicKey/ECPrivateKey 期间出错

转载 作者:行者123 更新时间:2023-12-02 02:17:57 24 4
gpt4 key购买 nike

希望在这里得到一些帮助...

我试图从未压缩的客户端公钥(0x04 |32字节点X|32字节点Y)和服务器私钥(openSSL生成base64)生成共享 key ,但在将服务器EC私钥转换为EC时出现错误关键对象。我需要这些来生成共享 secret

我正在使用 -1.曲线为brainpoolP256r12.使用openSSL生成服务器私钥(目前在代码中硬编码)3.客户端公共(public)以未压缩的方式共享(格式0x04 | 32字节点X | 32字节点Y)。

//Step 1 : Converting Client EC Public key (ephemeral) into actual EC Public key object (X509) 

byte[] clientECPublicKeybytes = DatatypeConverter.parseHexBinary("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5");

ECParameterSpec ecParameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolP256r1");

ECCurve curve = ecParameterSpec.getCurve(); ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(curve.decodePoint(clientECPublicKeybytes), ecParameterSpec);


KeyFactory kf = KeyFactory.getInstance("EC");


ECPublicKey ecClientPublicKey = (ECPublicKey)kf.generatePublic(pubKeySpec);


//Step 2 : Converting server EC private key ASN.1 to ECPrivateKey object

byte[] serverECCSkBytes = DatatypeConverter.parseBase64Binary("MHgCAQEEIA27nM1klj9pVxOzJrO4aBLFvXTtOJnf+vMhiv3HA+3noAsGCSskAwMCCAEBB6FEA0IABG1erLtLyTbC5yN8gVY4a0JPO5eefKftWMbSQij2Ks5TaNNuj/tqigFqsk1g/l2UBBkIx2KdpeiY8nVddwMpzho=");

KeyFactory keyFactory= KeyFactory.getInstance("EC","BC");

PKCS8EncodedKeySpec skSpec = new PKCS8EncodedKeySpec(serverECCSkBytes);

ECPrivateKey ecServerPrivateKey = (ECPrivateKey)keyFactory.generatePrivate(skSpec);

错误

2018-02-26 14:31:12.818[0;39m [31mERROR[0;39m [35m18096[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.a.c.c.C.[.[.[/].[dispatcherServlet]   [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.security.spec.InvalidKeySpecException: java.lang.IllegalArgumentException: wrong version for private key info] with root cause

java.security.spec.InvalidKeySpecException: java.lang.IllegalArgumentException: wrong version for private key info
at org.bouncycastle.jce.provider.JDKKeyFactory$EC.engineGeneratePrivate(Unknown Source) ~[bcprov-jdk15-140.jar:1.40.0]
at java.security.KeyFactory.generatePrivate(KeyFactory.java:366) ~[na:1.8.0_77]

最佳答案

TLDR:该私钥不是 PKCS8

OpenSSL 支持每种算法四种不同的 PEM 私钥格式(总共大约十几种);其中只有一种是未加密的 PKCS8,这是 Java PKCS8EncodedKeySpec 所需的格式,而您使用了 Java 不支持的另一种格式。与 How can I convert a .p12 to a .pem containing an unencrypted PKCS#1 private key block? 比较这是针对 RSA 的;对于 EC,两种“传统”格式由 SEC1 从 https://www.secg.org 定义。 (与 RSA 的 PKCS1 相比),而 PKCS8 格式(适用于所有算法,而不仅仅是 EC 和 RSA)由 PKCS8 定义。 OpenSSL 能够处理多种格式主要是因为 PEM 文件有一个非常重要的 BEGIN 行(以及不太重要的 END 行)来指定数据类型;您的文件在删除之前的类型为 EC PRIVATE KEY ,表示 SEC1 而不类型为 PRIVATE KEY ,表示 Java 使用的 PKCS8 未加密。

您有两个(或更多)选择:

  • 使用 openssl pkcs8 -topk8 -nocrypt 或仅 openssl pkey(在 1.0.0 及以上版本中)将 OpenSSL key 转换为 PKCS8 未加密的 PEM,或者生成首先将其作为 PKCS8 使用 genpkey 或可能使用 req -newkey(均在 1.0.0 及更高版本中)而不是 ecparam -genkey。在 PKCS8EncodedKeySpec 中使用 blob de-base64-ed

  • 如果除了 bcprov 之外,您还拥有或获得 bcpkix, 可以处理许多(也许是全部?)普通 Java 无法处理的 OpenSSL 格式。重建或恢复为原始 PEM 格式(可以在内存中),您可以使用 PEMReader 进行解析,然后使用 JcaPEMKeyConverter 进行转换(或者只是一个 KeyFactory)。

How to Load RSA Private Key From File 涵盖了这两者。对于 RSA,可以轻松修改为 EC。

  • 或者,由于您已经完成了 PEM 解析的一部分,因此您可以按照 PEMParser 的相同方式自行处理其余部分,仅针对私有(private)进行简化:
import java.security.*;import org.bouncycastle.asn1.ASN1Sequence;import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;import org.bouncycastle.asn1.x509.AlgorithmIdentifier;import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;...static void SO48996981BCparseECprivate () throws Exception {    byte[] server_sec1 = DatatypeConverter.parseBase64Binary("MHgCAQEEIA27nM1klj9pVxOzJrO4aBLFvXTtOJnf+vMhiv3HA+3noAsGCSskAwMCCAEBB6FEA0IABG1erLtLyTbC5yN8gVY4a0JPO5eefKftWMbSQij2Ks5TaNNuj/tqigFqsk1g/l2UBBkIx2KdpeiY8nVddwMpzho=");    ASN1Sequence seq = ASN1Sequence.getInstance(server_sec1);    org.bouncycastle.asn1.sec.ECPrivateKey pKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(seq);    AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, pKey.getParameters());    byte[] server_pkcs8 = new PrivateKeyInfo(algId, pKey).getEncoded();    KeyFactory fact = KeyFactory.getInstance ("EC","BC");    PrivateKey pkey = fact.generatePrivate (new PKCS8EncodedKeySpec(server_pkcs8));    // for test only:    System.out.println (pkey.getClass().getName() + " " + pkey.getAlgorithm());}
  • 最后,您实际上并不需要 Java 来实现此目的。 OpenSSL 可以在库(从您编写的代码中调用)或命令行 openssl pkeyutl -derive 中进行 ECDH key 协商/派生 - 尽管对于后者,您需要 PEM 文件中的 key em>:OpenSSL 支持的任何 PEM 格式的私钥(您已经拥有),但 X.509 subjectPublicKeyInfo 格式的对等公钥,根据给定的信息,您可能不支持并且可能必须构建。

关于java - 从未压缩的客户端临时公钥和 Open SSL 静态服务器私钥生成 ECPublicKey/ECPrivateKey 期间出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48996981/

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