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

从未压缩的客户端临时公钥和开放SSL静态服务器私钥生成ECPublicKey/ECPrivateKey时出错

许出野
2023-03-14

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

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

我在用- 1。曲线是brainpoolP256r1 2。服务器私有密钥是使用openSSL生成的(现在用代码硬编码)3。客户端公共以未压缩方式共享(格式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]

共有1个答案

魏松
2023-03-14

TLDR:那个私钥不是PKCS8

OpenSSL支持每种算法四种不同的PEM私钥格式(总共大约十几种);其中只有一个是PKCS8未加密的,这是Java PKCS8EncodedKeySpec要求的格式,而您使用的是Java不支持的另一个格式。与如何将. p12转换为包含未加密的PKCS#1私钥块的. pem相比?也就是RSA。对于EC,两种“传统”格式由https://www.secg.org的SEC1定义(相对于RSA的PKCS1),而PKCS8格式(对于所有算法,不仅仅是EC和RSA)由PKCS8定义。OpenSSL能够处理多种格式,主要是因为PEM文件有一个非常重要的开始行(和不太重要的结束行)来指定数据类型;在删除之前,您的文件具有表示SEC1的< code>EC私钥类型,而不是Java使用的表示PKCS8未加密的< code >私钥类型。

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

>

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

    如果除了bcprov之外,您还有或得到bcpkix,它可以处理许多(也许所有?)普通Java没有的OpenSSL格式。重建或恢复为原始PEM格式(可以在内存中),您可以使用PEMReader解析,然后使用JcaPEMKeyConverter(或仅使用KeyFactory)进行转换。

    这两者都包含在如何为RSA从文件中加载RSA私钥中,这可以很容易地为EC修改。

    • 或者,由于您已经完成了PEM解析的一部分,因此您可以按照PEMParser的相同方式自己处理其余部分,仅针对私人进行简化:
    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-派生中执行ECDH密钥协商/派生——尽管对于后者,您需要PEM文件中的密钥:OpenSSL支持的任何PEM格式的私钥(您已经拥有),但X.509 SubjectPublicKeyInfo格式的对等公钥,根据给定的信息,您可能不会也可能必须构建

  •  类似资料:
    • 问题内容: 我正在尝试在给定私钥和已知曲线的情况下生成公钥。下面是我的代码: 但是,当我打电话给 我时:我得到了例外:(不是我的拼写错误) 我似乎在计算错误,但是我不确定错误在哪里。 谢谢您的帮助! 问题答案: 如果我未来的自己需要解决方案:

    • 我需要用RSA-2048服务器公钥加密客户端私钥。我知道私钥明显比公钥长,我不确定是否可能。。。但我看到类似的任务是用Python完成的,所以我想知道您的看法。 crypto/rsa致命错误:对于rsa公钥大小,消息太长

    • 我以这种格式将私钥保存在DB中。 我需要从中提取公钥。openssl\u pkey\u get\u详细信息需要资源,但如何从字符串创建资源? 我试过这个 错误是openssl\u pkey\u get\u details()期望参数1是资源,给定布尔值 编辑1: 我试图从@kbarborak bellow获得解决方案,但$pk\u get是错误的: var_转储的输出为:

    • 我想在Java中通过SSL/TLS建立一个客户机服务器通信。服务器是多线程的。使用openssl,我充当自己的CA(为权威创建私钥和自签名证书)。现在我要为我的服务器和客户端创建密钥和证书,这些密钥和证书是从我创建的CA签名的。 1)我必须根据提示为每个客户创建证书和密钥吗?还是另一种“自动”方式,例如使用脚本? 2)我已经看到用于设置密钥库的代码 问题是我如何单独创建这些jks文件?public

    • 以下网站经常被引用,而且我认为是准确的: https://gobittest.appspot.com/Address 我试图在Golang中重现这些步骤,但第一步就失败了:-( 有人能给我提供一个Golang片段,给定ECDSA私钥,返回公钥吗?我想我可能具体指的是上述站点示例中的私钥指数和公钥指数。 i、 例如,给定随机生成的(十六进制编码的)私钥(指数?)<代码>E83385AF76B2B19

    • 我正在Erlang中创建一个应用程序,给定一个RSA私钥,它可以返回RSA公钥和与该priv密钥相关联的x509公钥。 ----只是一个更新---- 在花了一些时间了解x509并阅读了Erlang public_key文档后,我找到了一个解决方案: 如果我可以通过简单地获取模数和publicExponent,从“RSaprivateKey”生成“RSapublicKey”,那么生成这两个键的代码如