文档首页/ 数据加密服务 DEW/ 常见问题/ 密钥管理/ 如何将原始EC私钥转换成PKCS8格式的私钥对象?
更新时间:2025-05-13 GMT+08:00
分享

如何将原始EC私钥转换成PKCS8格式的私钥对象?

背景

EC私钥是个大整数,但是在密钥对导入场景,要求私钥对象是ASN.1编码之后,再对数据进行二进制编码,得到DER格式。仅通过OPENSSL命令无法获得。

本示例介绍如何将一个原始的256长度的EC私钥转换成PKCS8格式的私钥。

环境准备

  • 搭建JAVA环境,并引入bouncy castle 1.78及其以后的版本。
  • 环境安装OpenSSL 1.1.1m及以后的版本。

将私钥转换为PKCS8对象

有一个secp256k1的私钥,原始私钥16进制表示如下:

```DC23DA6E913444ABADCE2F42A3B7DC3958569948633EE80AEC46ACCA02523495```

示例的私钥仅作演示使用,请勿用到实际生产环境。

通过如下代码,将私钥转换成PKCS8对象:

```java
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.util.Base64;

public class RawEcPrivateKeyToPKCS8Object {
    public static void main(String[] args)
        throws InvalidParameterSpecException, NoSuchAlgorithmException, InvalidKeySpecException {

        Security.addProvider(new BouncyCastleProvider());

        KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());

        ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256k1");
        BigInteger d = new BigInteger("DC23DA6E913444ABADCE2F42A3B7DC3958569948633EE80AEC46ACCA02523495", 16);
        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecSpec);
        BCECPrivateKey ec = new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);

        ECPoint q = ecSpec.getG().multiply(((ECPrivateKey) ec).getD());
        ECPublicKeySpec pubSpec = new ECPublicKeySpec(q, ecSpec);
        PublicKey publicKey = keyFactory.generatePublic(pubSpec);

        BCECPrivateKey ec2 = new BCECPrivateKey("EC", ec.engineGetKeyParameters(), (BCECPublicKey) publicKey,
            ecPrivateKeySpec.getParams(), BouncyCastleProvider.CONFIGURATION);

        System.out.println(Base64.getEncoder().encodeToString(ec2.getEncoded()));
    }
}
```

执行上述代码,获得如下输出:

```ignorelang
MIGNAgEAMBAGByqGSM49AgEGBSuBBAAKBHYwdAIBAQQg3CPabpE0RKutzi9Co7fcOVhWmUhjPugK7EasygJSNJWgBwYFK4EEAAqhRANCAAQWiYvQT8cyVJx3wN85fXw0c2Ppv3SEsgnDaB96rWlz6G2bf2WhBJVD/jF5zb+5/oxgVIOYDe8EwqYtBwhIJ3Yh
```

使用ASN.1解码工具查看

```
 <SEQUENCE>
  <INTEGER/>
  <SEQUENCE>
   <OBJECT_IDENTIFIER Comment="ANSI X9.62 public key type" Description="ecPublicKey">1.2.840.10045.2.1</OBJECT_IDENTIFIER>
   <OBJECT_IDENTIFIER Comment="SECG (Certicom) named elliptic curve" Description="secp256k1">1.3.132.0.10</OBJECT_IDENTIFIER>
  </SEQUENCE>
  <OCTET_STRING>
   <SEQUENCE>
    <INTEGER>1</INTEGER>
    <OCTET_STRING>0xDC23DA6E913444ABADCE2F42A3B7DC3958569948633EE80AEC46ACCA02523495</OCTET_STRING>
    <NODE Sign="a0">
     <OBJECT_IDENTIFIER Comment="SECG (Certicom) named elliptic curve" Description="secp256k1">1.3.132.0.10</OBJECT_IDENTIFIER>
    </NODE>
    <NODE Sign="a1">
     <BIT_STRING Bits="520">0x000416898BD04FC732549C77C0DF397D7C347363E9BF7484B209C3681F7AAD6973E86D9B7F65A1049543FE3179CDBFB9FE8C605483980DEF04C2A62D070848277621</BIT_STRING>
    </NODE>
   </SEQUENCE>
  </OCTET_STRING>
 </SEQUENCE>
```

将如下内容写入到命名为“ec_private_key.pem”的文件中:

```ignorelang
-----BEGIN PRIVATE KEY-----
MIGNAgEAMBAGByqGSM49AgEGBSuBBAAKBHYwdAIBAQQg3CPabpE0RKutzi9Co7fcOVhWmUhjPugK7EasygJSNJWgBwYFK4EEAAqhRANCAAQWiYvQT8cyVJx3wN85fXw0c2Ppv3SEsgnDaB96rWlz6G2bf2WhBJVD/jF5zb+5/oxgVIOYDe8EwqYtBwhIJ3Yh
-----END PRIVATE KEY-----
```

执行如下命令:查看EC密钥的信息:

```shell
openssl ec -in ec_private_key.pem -text
```
```ignorelang
read EC key
Private-Key: (256 bit)
priv:
    dc:23:da:6e:91:34:44:ab:ad:ce:2f:42:a3:b7:dc:
    39:58:56:99:48:63:3e:e8:0a:ec:46:ac:ca:02:52:
    34:95
pub:
    04:16:89:8b:d0:4f:c7:32:54:9c:77:c0:df:39:7d:
    7c:34:73:63:e9:bf:74:84:b2:09:c3:68:1f:7a:ad:
    69:73:e8:6d:9b:7f:65:a1:04:95:43:fe:31:79:cd:
    bf:b9:fe:8c:60:54:83:98:0d:ef:04:c2:a6:2d:07:
    08:48:27:76:21
ASN1 OID: secp256k1
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEINwj2m6RNESrrc4vQqO33DlYVplIYz7oCuxGrMoCUjSVoAcGBSuBBAAK
oUQDQgAEFomL0E/HMlScd8DfOX18NHNj6b90hLIJw2gfeq1pc+htm39loQSVQ/4x
ec2/uf6MYFSDmA3vBMKmLQcISCd2IQ==
-----END EC PRIVATE KEY-----

```

后续可以正常执行转成DER命令:

```shell
openssl pkcs8 -topk8 -inform PEM -outform DER -in ec_private_key.pem -out ec_private_key.der -nocrypt```

相关文档