You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:06:01