- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
希望在这里得到一些帮助...
我试图从未压缩的客户端公钥(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。
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());}
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/
我是一名优秀的程序员,十分优秀!