英文:
Elliptic Curve Private Key Length in Java
问题
我使用"secp256r1"曲线创建了一个EC密钥对。这是一个256位的曲线,私钥应该是256位(32字节)。但我得到的是39字节的私钥。以下是我的代码:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); //提供者是SunEC版本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); // 期望长度为32,但实际为39
我正在使用JDK 1.8.0_144和BouncyCastle库。以下是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>
如何获取32字节的私钥?
英文:
I created a EC key pair using "secp256r1" curve. It is 256-bit curve and private key should be 256 bits (32 bytes). But what I'm getting is 39 bytes private key. 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.
Here is 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?
答案1
得分: 6
以下是您要求的翻译内容:
PKCS8 的与算法相关部分,在序列的第二个元素位置,对于 EC 来说本身就是一个 DER 编码,其结构是 SEC1 中的 ECPrivateKey,也在 rfc5915 中有文档记录。对于 SunEC,这是一个 SEQUENCE,包含 INTEGER 类型的版本和 OCTETSTRING,其中包含实际的私钥字节;可选的 context-0 参数和 context-1 公钥被省略。因此,您需要解析它:
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();
// 稍作重新组织
DEROctetString wrapped = (DEROctetString) DERSequence.getInstance(pkcs8).getObjectAt(2);
System.out.println(wrapped.getOctets().length);
// 新增部分
DEROctetString raw = (DEROctetString) DERSequence.getInstance(wrapped.getOctets()).getObjectAt(1);
System.out.println(raw.getOctets().length);
由于您使用的是 BouncyCastle,您可以使用 org.bouncycastle.asn1.pkcs.PrivateKeyInfo
这个 BouncyCastle 类来解析 PKCS8,而不是手动解析:
PrivateKeyInfo info = PrivateKeyInfo.getInstance(DERSequence.getInstance(pkcs8));
DEROctetString raw2 = (DEROctetString)(DERSequence.getInstance(info.parsePrivateKey())).getObjectAt(1);
System.out.println(raw2.getOctets().length);
最后,您可以直接从 ECPrivateKey
对象中获取私钥值,将其作为 BigInteger
值获取,然后转换为字节数组。尽管其长度是可变的,而不是传统的固定长度,因此您可能需要进行调整:
byte[] bytes = ((ECPrivateKey) privateKey).getS().toByteArray();
System.out.println(bytes.length);
// 可能需要进行左侧修剪或填充零
英文:
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. For SunEC this is a SEQUENCE of INTEGER version and OCTETSTRING containing the actual privatekey bytes; the optional context-0 parameters and context-1 publickey are omitted. 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
:
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:
byte[] bytes = ((ECPrivateKey)privateKey).getS().toByteArray();
System.out.println(bytes.length);
// may need left-trim or pad with zero(s)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论