是否可以使用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
答案 0 :(得分:1)
顾名思义,从Java PrivateKey.getEncoded()
返回的值是一个编码的私钥。具体来说,as documented in the superclass Key
是ASN.1(DER)的 PKCS#8 = Public-Key Cryptography Standard #8, Private Key Information Syntax编码。 PKCS#8处理各种不同的公钥算法的私钥,除了实际密钥外,还包含元数据,即标识算法和算法任何参数的“ AlgorithmIdentifier”;对于ECC算法(ECDSA,ECDH,ECMQV等共享一种密钥格式),这些参数指定了使用的椭圆曲线组,尽管该规范有多种选择,但实际上每个人(包括Java)都使用“ namedCurve'选项,它通过ASN.1 OID(也称为对象标识符)定义曲线组。
然后,PKCS#8结构包含实际的私钥数据,这些数据“包装”在OCTET STRING中,其格式根据算法而有所不同。对于ECC,此格式在SEC1 by SECG/Certicom中定义(AFAICT),并且包含实际私钥值(数字,表示为OCTET STRING)以及可选曲线规范和公钥。< / p>
您的第一个代码使用BouncyCastle,Bouncy使用包含可选曲线规范和公共密钥的包装值来生成编码,从而使编码变长。
默认情况下,您的第二个代码使用Oracle / Sun提供程序(SunEC),该提供程序在不使用这些选项的情况下生成编码,但仍包含所需的AlgorithmIdentifier,从而使其比实际私钥值更长。它还使用不同的曲线:用整数256初始化SunEC生成器时选择secp256r1(又名P-256,prime256v1)而不是secp256k1。如果将其更改为使用new ECGenParameterSpec("secp256k1")
作为参数,则SunEC还将生成secp256k1,但没有选项,给出64字节编码。
在两种情况下,如果只需要私钥 number ,则强制转换为java.security.interfaces.ECPrivateKey
并使用getS()
。如果希望按照常规方式将结果存储在字节/八位字节数组中,请注意BigInteger.toByteArray()
返回一个可变长度的结果,并且您通常需要保留零修剪或填充它。
如果您 did 需要公钥,则它具有使用“ X.509”编码的相似方案,其中包含AlgorithmIdentifier和包裹实际公钥值的BIT STRING,因此比原始公钥值。但是,在这种情况下,interfaces.ECPublicKey
和spec.ECPoint
不会为您构建编码。使用Bouncy-only类型会更方便。