如何用liboqs-go生成Dilithium密钥并转换为OpenSSL兼容的PEM格式
解决liboqs-go生成后量子密钥转OpenSSL兼容PEM格式的问题
你的核心问题是:liboqs-go生成的Dilithium2密钥是算法原生的二进制字节流,而OpenSSL需要符合X.509标准的PEM编码密钥(封装在ASN.1/DER结构中)才能生成CSR和证书。以下是完整的解决方案:
一、前提:使用支持后量子算法的OpenSSL
原生OpenSSL不支持Dilithium等后量子算法,你需要使用打了OQS补丁的OpenSSL版本,可从OQS官方渠道获取编译好的版本或自行编译。
二、修改Go代码,生成OpenSSL兼容的PEM密钥
需要把liboqs返回的原始密钥字节,封装成符合OQS定义的ASN.1结构,再编码为PEM格式。下面是修改后的完整代码:
package main import ( "crypto/x509" "encoding/asn1" "encoding/pem" "io/ioutil" "log" "github.com/open-quantum-safe/liboqs-go/oqs" ) // Dilithium2的OID,来自OQS官方定义 var dilithium2OID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 2, 267, 7, 4, 4} // 将原始公钥字节转换为PEM格式 func publicKeyToPEM(rawPubKey []byte) ([]byte, error) { // 构造SubjectPublicKeyInfo结构 spki := x509.SubjectPublicKeyInfo{ Algorithm: x509.AlgorithmIdentifier{ ObjectID: dilithium2OID, // Dilithium算法无额外参数,设为nil Parameters: asn1.NullRawValue, }, PublicKey: rawPubKey, } // 编码为DER格式 derBytes, err := asn1.Marshal(spki) if err != nil { return nil, err } // 封装为PEM return pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", Bytes: derBytes, }), nil } // 将原始私钥字节转换为PEM格式 func privateKeyToPEM(rawPrivKey []byte) ([]byte, error) { // 构造PrivateKeyInfo结构 pkInfo := x509.PrivateKeyInfo{ Algorithm: x509.AlgorithmIdentifier{ ObjectID: dilithium2OID, Parameters: asn1.NullRawValue, }, PrivateKey: rawPrivKey, } // 编码为DER格式 derBytes, err := asn1.Marshal(pkInfo) if err != nil { return nil, err } // 封装为PEM return pem.EncodeToMemory(&pem.Block{ Type: "PRIVATE KEY", Bytes: derBytes, }), nil } func generateKeys() ([]byte, []byte, error) { signer := oqs.Signature{} err := signer.Init("dilithium2", nil) if err != nil { return nil, nil, err } defer signer.Clean() publicKeyRaw, err := signer.GenerateKeyPair() if err != nil { return nil, nil, err } secretKeyRaw := signer.ExportSecretKey() // 转换为PEM格式 publicKeyPEM, err := publicKeyToPEM(publicKeyRaw) if err != nil { return nil, nil, err } secretKeyPEM, err := privateKeyToPEM(secretKeyRaw) if err != nil { return nil, nil, err } return publicKeyPEM, secretKeyPEM, nil } func main() { publicKeyPEM, secretKeyPEM, err := generateKeys() if err != nil { log.Fatalf("密钥生成失败: %v", err) } // 写入PEM文件 err = ioutil.WriteFile("public.pem", publicKeyPEM, 0644) if err != nil { log.Fatalf("写入公钥文件失败: %v", err) } err = ioutil.WriteFile("private.pem", secretKeyPEM, 0600) if err != nil { log.Fatalf("写入私钥文件失败: %v", err) } log.Println("PEM格式密钥生成完成") }
三、使用PEM密钥生成CSR和证书
用带OQS补丁的OpenSSL执行以下命令:
1. 生成CSR
openssl req -new -key private.pem -out csr.pem -subj "/CN=your-domain.com"
2. 生成自签证书
openssl x509 -req -in csr.pem -signkey private.pem -out cert.pem -days 365
关键说明
- 不同后量子算法的OID不同,比如Dilithium3的OID是
1.3.6.1.4.1.2.267.7.4.5,需要根据使用的算法替换对应的OID - 私钥文件权限设为0600,符合安全规范
- 确保你的OpenSSL版本已正确加载OQS插件,可通过
openssl list -signature-algorithms查看是否包含dilithium2
内容的提问来源于stack exchange,提问作者T_21
相关产品推荐
相关产品推荐

