java/scala 中生成 ecdsa 32 字节私钥
Generation ecdsa 32-byte private key in java/scala
是否可以使用 KeyPairGenerator 在 java 中生成 ecdsa 32 字节私钥?我的意思是 keys.getPublic.getEncoded.length 将 return 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
从 Java PrivateKey.getEncoded()
返回的值是 编码的 私钥,正如其名称所示。具体来说 as documented in the superclass Key
it is an ASN.1 (DER) encoding of PKCS#8 = Public-Key Cryptography Standard #8, Private Key Information Syntax。 PKCS#8 处理各种不同 public 密钥算法的私钥,并包含除实际密钥之外的元数据,即识别算法和算法的任何参数的 'AlgorithmIdentifier';对于 ECC 算法(ECDSA、ECDH、ECMQV 等共享一种密钥格式),这些参数指定了使用的椭圆曲线组,尽管此规范有多个选项,但实际上每个人都包括这里 Java ,使用 'namedCurve' 选项,该选项通过 ASN.1 OID aka 对象标识符定义曲线组。
然后 PKCS#8 结构包含实际的私钥数据,'wrapped' 在一个 OCTET STRING 中,其格式因算法而异。对于 ECC,此格式在 SEC1 by SECG/Certicom 中定义 (AFAICT) 并包含实际私钥值(一个数字,表示为 OCTET STRING)加上 可选 曲线规范和 public键。
您的第一个代码使用 BouncyCastle,Bouncy 生成包含可选曲线规范和 public 密钥的包装值的编码,使其更长。
您的第二个代码默认使用 Oracle/Sun 提供程序 (SunEC),它生成没有这些选项的编码,但仍包含所需的 AlgorithmIdentifier,使其比实际私钥值更长。它还使用 不同的曲线 :用整数 256 初始化 SunEC 生成器选择 secp256r1(又名 P-256,prime256v1)而不是 secp256k1。如果您将其更改为使用 new ECGenParameterSpec("secp256k1")
作为参数,那么 SunEC 还将生成 secp256k1,但没有选项,提供 64 字节编码。
在这两种情况下,如果您只需要私钥 number,请转换为 java.security.interfaces.ECPrivateKey
并使用 getS()
。如果您想要 byte/octet 数组中的结果,按照惯例,请注意 BigInteger.toByteArray()
returns 一个可变长度的结果,您通常需要将其保留为零 trim 或对其进行填充。
如果您做了想要public密钥,它有一个类似的方案,使用'X.509'编码,其中包含一个AlgorithmIdentifier和一个BIT STRING包装实际 public 键值,因此比原始 public 键值长。但是在这种情况下 interfaces.ECPublicKey
和 spec.ECPoint
不会为您构建编码;使用仅限 Bouncy 的类型会更方便。
是否可以使用 KeyPairGenerator 在 java 中生成 ecdsa 32 字节私钥?我的意思是 keys.getPublic.getEncoded.length 将 return 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
从 Java PrivateKey.getEncoded()
返回的值是 编码的 私钥,正如其名称所示。具体来说 as documented in the superclass Key
it is an ASN.1 (DER) encoding of PKCS#8 = Public-Key Cryptography Standard #8, Private Key Information Syntax。 PKCS#8 处理各种不同 public 密钥算法的私钥,并包含除实际密钥之外的元数据,即识别算法和算法的任何参数的 'AlgorithmIdentifier';对于 ECC 算法(ECDSA、ECDH、ECMQV 等共享一种密钥格式),这些参数指定了使用的椭圆曲线组,尽管此规范有多个选项,但实际上每个人都包括这里 Java ,使用 'namedCurve' 选项,该选项通过 ASN.1 OID aka 对象标识符定义曲线组。
然后 PKCS#8 结构包含实际的私钥数据,'wrapped' 在一个 OCTET STRING 中,其格式因算法而异。对于 ECC,此格式在 SEC1 by SECG/Certicom 中定义 (AFAICT) 并包含实际私钥值(一个数字,表示为 OCTET STRING)加上 可选 曲线规范和 public键。
您的第一个代码使用 BouncyCastle,Bouncy 生成包含可选曲线规范和 public 密钥的包装值的编码,使其更长。
您的第二个代码默认使用 Oracle/Sun 提供程序 (SunEC),它生成没有这些选项的编码,但仍包含所需的 AlgorithmIdentifier,使其比实际私钥值更长。它还使用 不同的曲线 :用整数 256 初始化 SunEC 生成器选择 secp256r1(又名 P-256,prime256v1)而不是 secp256k1。如果您将其更改为使用 new ECGenParameterSpec("secp256k1")
作为参数,那么 SunEC 还将生成 secp256k1,但没有选项,提供 64 字节编码。
在这两种情况下,如果您只需要私钥 number,请转换为 java.security.interfaces.ECPrivateKey
并使用 getS()
。如果您想要 byte/octet 数组中的结果,按照惯例,请注意 BigInteger.toByteArray()
returns 一个可变长度的结果,您通常需要将其保留为零 trim 或对其进行填充。
如果您做了想要public密钥,它有一个类似的方案,使用'X.509'编码,其中包含一个AlgorithmIdentifier和一个BIT STRING包装实际 public 键值,因此比原始 public 键值长。但是在这种情况下 interfaces.ECPublicKey
和 spec.ECPoint
不会为您构建编码;使用仅限 Bouncy 的类型会更方便。