如何手动生成X.509格式RSA证书?求详细分步指南
分步开发Dart版RSA X.509证书生成库
一、先补全核心概念(ChatGPT没讲透的部分)
- X.509证书本质:由ASN.1(抽象语法标记)定义的结构化数据,核心包含版本号、唯一序列号、签名算法标识、颁发者信息、有效期、主体信息、主体公钥、扩展字段(可选)、签名值这几个关键部分。
- DER编码规则:ASN.1的二进制序列化标准,所有X.509和PKCS系列数据都用它编码,核心遵循TLV(类型-长度-值)结构:每个数据块由「类型字节」「长度字段」「实际值」三部分组成,比如整数对应类型0x02,序列结构对应类型0x30。
二、结合你提供的Dart库的开发步骤
步骤1:生成RSA密钥对(复用现有库能力)
用einfache_krypto库快速完成密钥对生成:
- 生成两个2048位的大素数
p和q(库内置Miller-Rabin素性检测,无需自行实现) - 计算模数
n = p * q,欧拉函数φ(n) = (p-1) * (q-1) - 采用标准公钥指数
e = 65537(0x10001,确保与φ(n)互质) - 调用库的扩展欧几里得算法实现,计算私钥指数
d,满足(e * d) mod φ(n) = 1 - 保存所有密钥组件:
n、e、d、p、q(PKCS#8私钥需要这些完整组件)
步骤2:DER编码X.509格式公钥
X.509公钥的ASN.1结构固定,需按以下层级编码:
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, -- RSA的OID为1.2.840.113549.1.1.1 parameters ANY DEFINED BY algorithm OPTIONAL -- RSA此处为NULL }
结合number_system库实现编码:
- 将大数
n和e转为DER INTEGER格式:把大数转字节数组,若字节数组最高位是0x80及以上,需在头部加一个0x00字节(避免被解析为负数) - 把
n和e的DER INTEGER打包成SEQUENCE(类型0x30),得到RSA公钥的核心DER数据 - 构造AlgorithmIdentifier的DER:将RSA的OID(编码为0x06 0x09 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01)和NULL值(0x05 0x00)打包成SEQUENCE
- 把AlgorithmIdentifier的DER和公钥核心DER打包成外层SEQUENCE,再套上BIT STRING类型,最终得到完整的X.509公钥DER
步骤3:DER编码PKCS#8格式私钥
PKCS#8私钥的ASN.1结构如下:
PrivateKeyInfo ::= SEQUENCE { version Version, -- 固定为INTEGER 0 privateKeyAlgorithm AlgorithmIdentifier, -- 与公钥的AlgorithmIdentifier一致 privateKey OCTET STRING, -- RSA私钥核心的DER编码 attributes [0] IMPLICIT Attributes OPTIONAL -- 自签名可忽略 }
实现步骤:
- 构造RSA私钥核心的ASN.1 SEQUENCE,包含版本(INTEGER 0)、
n、e、d、p、q等组件的DER INTEGER - 将这个核心SEQUENCE的DER数据打包成OCTET STRING
- 把version、privateKeyAlgorithm、privateKey按顺序打包成外层SEQUENCE,得到PKCS#8私钥的DER
步骤4:生成自签名X.509证书
X.509证书由「待签名证书(TBSCertificate)」「签名算法标识」「签名值」三部分组成,结构如下:
Certificate ::= SEQUENCE { tbsCertificate TBSCertificate, signatureAlgorithm AlgorithmIdentifier, -- 比如SHA256withRSA,OID为1.2.840.113549.1.1.11 signatureValue BIT STRING }
核心开发流程:
- 构建TBSCertificate的各个字段:
- version:INTEGER 2(对应X.509 v3版本)
- serialNumber:用当前时间戳转成唯一大数(确保全局唯一)
- signature:与最终签名算法一致(比如SHA256withRSA)
- issuer:主体名称(例如
CN=MySelfSignedCert,用ASN.1的Name结构,由多个RelativeDistinguishedName组成) - validity:设置有效期,用UTCTime类型编码起始和结束时间
- subject:与issuer相同(自签名证书)
- subjectPublicKeyInfo:步骤2生成的公钥结构
- extensions:可选添加BasicConstraints扩展,标记
CA:FALSE
- 将TBSCertificate的所有字段按ASN.1结构打包成DER字节数组
- 用SHA256哈希TBSCertificate的DER数据
- 用RSA私钥对哈希值进行签名(调用
einfache_krypto的RSA签名实现) - 把TBSCertificate的DER、signatureAlgorithm、signatureValue打包成外层SEQUENCE,得到完整的自签名X.509证书DER
三、关键编码细节
- 常用ASN.1类型码:
- SEQUENCE: 0x30
- INTEGER: 0x02
- BIT STRING: 0x03
- OCTET STRING: 0x04
- OBJECT IDENTIFIER: 0x06
- UTCTime: 0x17
- 长度字段编码规则:
- 若数据长度<128,直接用单字节表示长度
- 若长度≥128,第一个字节为
0x80 + 长度的字节数,后续字节为长度的二进制表示
- 大数转DER INTEGER注意事项:正整数的字节数组最高位若为0x80及以上,必须在头部添加0x00字节,否则会被ASN.1解析器识别为负数
四、参考标准文档
- RFC 5280:X.509证书标准官方定义
- RFC 3447:PKCS#1 RSA算法标准
- RFC 5208:PKCS#8私钥格式标准
内容的提问来源于stack exchange,提问作者NewToPi
相关产品推荐
相关产品推荐

