[英]Elliptic Curve Private Key Length in Java
I created a EC key pair using "secp256r1" curve.我使用“secp256r1”曲线创建了一个 EC 密钥对。 It is 256-bit curve and private key should be 256 bits (32 bytes).
它是 256 位曲线,私钥应为 256 位(32 字节)。 But what I'm getting is 39 bytes private key.
但我得到的是 39 字节的私钥。 Here is my code
这是我的代码
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); //Provider is SunEC version 1.8
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
kpg.initialize(ecSpec, new SecureRandom());
KeyPair ecKeyPair = kpg.generateKeyPair();
PrivateKey privateKey = ecKeyPair.getPrivate();
ASN1Sequence sequence = DERSequence.getInstance(privateKey.getEncoded());
DEROctetString subjectPrivateKey = (DEROctetString) sequence.getObjectAt(2);
byte[] privateKeyBytes = subjectPrivateKey.getOctets();
System.out.println("PrivateKeyBytes.length: " + privateKeyBytes.length); // Expected length is 32, but actual is 39
I'm using JDK 1.8.0_144 and BouncyCastle library.我正在使用 JDK 1.8.0_144 和 BouncyCastle 库。 Here is pom.xml
这是 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>pki</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-debug-jdk15on</artifactId>
<version>1.65</version>
</dependency>
</dependencies>
</project>
How to get 32 bytes of private key?如何获得32字节的私钥?
The algorithm-dependent part of PKCS8, at element #2 of the sequence, for EC is itself a DER encoding, of the SEC1 structure ECPrivateKey, also documented at rfc5915 . PKCS8 的算法相关部分,在序列的元素#2,对于 EC,它本身就是一个 DER 编码,属于SEC1结构 ECPrivateKey,也记录在rfc5915 中。 For SunEC this is a SEQUENCE of INTEGER version and OCTETSTRING containing the actual privatekey bytes;
对于 SunEC,这是包含实际私钥字节的整数版本和 OCTETSTRING 的序列; the optional context-0 parameters and context-1 publickey are omitted.
省略了可选的 context-0 参数和 context-1 公钥。 So you need to parse that:
所以你需要解析:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC",args[0]);
kpg.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
KeyPair ecKeyPair = kpg.generateKeyPair();
PrivateKey privateKey = ecKeyPair.getPrivate();
byte[] pkcs8 = privateKey.getEncoded();
// slightly reorganized
DEROctetString wrapped = (DEROctetString) DERSequence.getInstance(pkcs8).getObjectAt(2);
System.out.println (wrapped.getOctets().length);
// added
DEROctetString raw = (DEROctetString) DERSequence.getInstance( wrapped.getOctets() ).getObjectAt(1);
System.out.println (raw.getOctets().length);
Since you are using BouncyCastle, rather than manually parse the PKCS8 you can use the BouncyCastle class for org.bouncycastle.asn1.pkcs.PrivateKeyInfo
:由于您使用的是 BouncyCastle,而不是手动解析 PKCS8,您可以将 BouncyCastle 类用于
org.bouncycastle.asn1.pkcs.PrivateKeyInfo
:
PrivateKeyInfo info = PrivateKeyInfo.getInstance (DERSequence.getInstance(pkcs8));
DEROctetString raw2 = (DEROctetString)( DERSequence.getInstance(info.parsePrivateKey()) ).getObjectAt(1);
System.out.println (raw2.getOctets().length);
and finally, rather than going through the encoding, you can get the privatekey value directly from the ECPrivateKey
object as a BigInteger
value, which can be converted to a byte array, although it is variable length instead of the fixed length conventionally used for EC privatekeys, so you may need to adjust it:最后,无需经过编码,您可以直接从
ECPrivateKey
对象中获取私钥值作为BigInteger
值,该值可以转换为字节数组,尽管它是可变长度而不是常规用于 EC 私钥的固定长度,所以你可能需要调整它:
byte[] bytes = ((ECPrivateKey)privateKey).getS().toByteArray();
System.out.println(bytes.length);
// may need left-trim or pad with zero(s)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.