在 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.ECPublicKey
和 spec.ECPoint
不会为您构建编码;使用 Bouncy-only 类型会更方便。
【讨论】:
以上是关于在 java/scala 中生成 ecdsa 32 字节私钥的主要内容,如果未能解决你的问题,请参考以下文章
如何在 NodeJS 中生成 ECDSA 签名而不需要 PEM 密钥格式?