在 java/scala 中生成 ecdsa 32 字节私钥

Posted

技术标签:

【中文标题】在 java/scala 中生成 ecdsa 32 字节私钥【英文标题】:Generation ecdsa 32-byte private key in java/scala 【发布时间】:2018-09-12 16:24:13 【问题描述】:

是否可以使用 KeyPairGenerator 在 java 中生成 ecdsa 32 字节私钥?我的意思是 keys.getPublic.getEncoded.length 将返回 32 我尝试生成私钥,但大小为 144 字节

//keys.getPrivate.getEncoded.length - 144 bytes
val ecSpec: ECNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("secp256k1")
val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC")
val secRandom = new SecureRandom()
keyPairGenerator.initialize(ecSpec, secRandom)
val keys = keyPairGenerator.generateKeyPair

//keys.getPrivate.getEncoded.length - 67 bytes
val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance("EC")
keyPairGenerator.initialize(256)
val keys = keyPairGenerator.generateKeyPair

【问题讨论】:

欢迎来到***。请通过该站点的tour 了解*** 的工作原理以及如何提出好的问题。然后回来edit你的问题。包括您尝试过的代码minimal reproducible example,以及任何错误消息。问具体问题。大多数人都乐于提供帮助,但不想为你做你的工作。诸如“我该如何做 x?”之类的问题。没有显示出任何研究工作的结果很可能会被忽略。 你的意思是.getPrivate不是.getPublic; secp256k1 原始公钥(未压缩点)是 65 个字节而不是 32 个。 【参考方案1】:

Java PrivateKey.getEncoded() 返回的值是一个编码 私钥,顾名思义。特别是as documented in the superclass Key,它是PKCS#8 = Public-Key Cryptography Standard #8, Private Key Information Syntax 的ASN.1 (DER) 编码。 PKCS#8 处理各种不同公钥算法的私钥,除了实际密钥之外还包含元数据,即标识算法和算法的任何参数的“算法标识符”;对于 ECC 算法(ECDSA、ECDH、ECMQV 和更多共享一个密钥格式),这些参数指定使用的椭圆曲线组,尽管本规范有几个选项,但实际上每个人,包括这里的 Java,都使用 ' namedCurve' 选项,它通过 ASN.1 OID aka Object Identifier 定义曲线组。

然后,PKCS#8 结构包含实际的私钥数据,“包装”在一个八位字节字符串中,其格式因算法而异。对于 ECC,此格式在 SEC1 by SECG/Certicom 中定义 (AFAICT),包含实际的私钥值(一个数字,表示为 OCTET STRING)加上可选曲线规范和公钥。

您的第一个代码使用 BouncyCastle,Bouncy 使用包含可选曲线规范和公钥的包装值生成编码,使其更长。

您的第二个代码默认使用 Oracle/Sun 提供程序 (SunEC),它生成不带这些选项的编码,但仍包含所需的 AlgorithmIdentifier,使其比实际私钥值长。它还使用不同的曲线:使用整数 256 初始化 SunEC 生成器会选择 secp256r1(又名 P-256,prime256v1)而不是 secp256k1。如果您将其更改为使用 new ECGenParameterSpec("secp256k1") 作为参数,那么 SunEC 也将生成 secp256k1,但没有选项,提供 64 字节编码。

在这两种情况下,如果您只需要私钥数字,请转换为java.security.interfaces.ECPrivateKey 并使用getS()。如果您希望按照惯例将结果保存在字节/八位字节数组中,请注意BigInteger.toByteArray() 返回一个可变长度的结果,您通常需要保留零修剪或填充它。

如果您确实想要公钥,它有一个使用“X.509”编码的类似方案,其中包含一个算法标识符和一个包装实际公钥值的位字符串,因此比原始公钥值。但是在这种情况下,interfaces.ECPublicKeyspec.ECPoint 不会为您构建编码;使用 Bouncy-only 类型会更方便。

【讨论】:

以上是关于在 java/scala 中生成 ecdsa 32 字节私钥的主要内容,如果未能解决你的问题,请参考以下文章

如何在 NodeJS 中生成 ECDSA 签名而不需要 PEM 密钥格式?

如何使用 Hyperledger Fabric 中生成的 ECDSA 私钥和公钥进行加密和解密

如何在 Go 中存储 ECDSA 私钥

Chisel 的推荐 Java/Scala 设置

如何在stm32f303中生成时间戳?

在 win32 服务 (C++) 中生成 casablanca http_listener 的问题