java - Java 中的椭圆曲线私钥长度

标签 java cryptography bouncycastle elliptic-curve

我使用“secp256r1”曲线创建了一个 EC key 对。它是 256 位的曲线,私钥应该是 256 位(32 字节)。但我得到的是 39 字节的私钥。这是我的代码

 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 

我正在使用 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字节的私钥?

最佳答案

PKCS8 的算法相关部分,位于序列的元素 #2,因为 EC 本身是 SEC1 的 DER 编码结构 ECPrivateKey,也记录在 rfc5915 .对于 SunEC,这是一个包含实际私钥字节的 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();
    
    // 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);

由于您使用的是 BouncyCaSTLe,您可以使用 BouncyCaSTLe 类用于 org.bouncycaSTLe.asn1.pkcs.PrivateKeyInfo,而不是手动解析 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 值,可以将其转换为字节array,尽管它是可变长度而不是通常用于 EC 私钥的固定长度,因此您可能需要调整它:

    byte[] bytes = ((ECPrivateKey)privateKey).getS().toByteArray();
    System.out.println(bytes.length);
    // may need left-trim or pad with zero(s)

关于java - Java 中的椭圆曲线私钥长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63568619/

相关文章:

c# - 未找到 System.Security.Cryptography

c - PEM_write_PrivateKey() 函数未将 RSA 私钥存储在 private.pem 文件中

java - 使用 BouncyCaSTLe 在 Java 中使用 ECIES 进行加密

android - 在Android上将Apache Mina与SslFilter一起使用

java - 持久化数亿个 SQL Timestamp 对象时性能会受到影响

java - environment.getProperty ("property") 是否产生与 @Value ("property"相同的值)

java - 工作日计算器逻辑错误 - Java

java - (已弃用的)myThread.stop()的有效用例?

java - 为什么不同的 key 也可以解密 JWE 加密

android - 如何为 Mac OSX Maverick 配置 BouncyCaSTLe