Delphi+OpenSSL将PEM私钥转DER时与原文件不一致问题排查
墨西哥电子发票私钥DER还原异常问题
背景
在墨西哥电子发票体系中,税务机关会向纳税人发放DER格式的数字签名证书/密钥对(.cer、.key文件),其中私钥采用des-ede3-cbc加密的PKCS8格式,用于签署发票XML并提交至PAC服务完成二次签名。我们基于Delphi 10和OpenSSL开发开票系统,用户上传.cer/.key文件后,系统会将其转换为PEM格式存储到数据库,不再保留原文件。
原转换代码
.cer转PEM代码
Var infile, outfile : pBIO; x : pX509; n : Integer; PEM, fn : AnsiString; // 存储文件名 BIO_read_filename(infile,PansiChar(fn)); x := d2i_X509_bio(infile,Nil); outfile := BIO_new(BIO_s_mem); PEM_write_bio_X509(outfile,x); n := BIO_pending(outfile); SetLength(PEM,n); BIO_read(outfile,@PEM[1],n) // 将PEM内容保存到数据库
.key转PEM代码
Var infile, outfile : pBIO; p8 : pX509_SIG; p8inf : pPKCS8_Priv_Key_Info; n : Integer; x : pEVP_PKEY; PEM, fn : AnsiString; infile := BIO_new(BIO_s_file); BIO_read_filename(infile,PANSICHAR(fn)); p8 := d2i_PKCS8_bio(infile,Nil); p8inf := PKCS8_decrypt(p8,_PCHAR(Password),Length(Password)); // Password为传入的参数 x := EVP_PKCS82PKEY(p8inf); outfile := BIO_new(BIO_s_mem); PEM_write_bio_PKCS8PrivateKey(outfile,x,Nil,_PCHAR(Password),Length(Password),Nil,Nil); n := BIO_pending(outfile); SetLength(PEM,n); BIO_read(outfile,@PEM[1],n) // 将PEM内容保存到数据库
问题场景
因新需求需要从数据库存储的PEM格式还原出原DER格式文件,.cer文件还原正常,但私钥还原出现异常。
私钥还原代码
Var infile, outfile : pBIO; n : Integer; pRSAKey : pEVP_PKEY; DER : TArray<Byte>; infile := BIO_new(BIO_s_mem); BIO_puts(infile,PAnsiChar(PEM_key_saved)); PEM_read_bio_PrivateKey(infile,pRSAKey,Nil,PAnsiChar(Password)); outfile := BIO_new(BIO_s_mem); i2d_PKCS8PrivateKey_bio(outfile,pRSAKey,EVP_des_ede3_cbc(),Nil,0,Nil,PAnsiChar(Password)); n := BIO_pending(outfile); SetLength(DER,n); BIO_read(outfile,@DER[0],n) // DER应与原.key文件字节完全一致
异常现象
- 还原后的new.key与原original.key文件大小相同,但内容不一致;
- 使用
openssl pkcs8解析两者,输出的RSA私钥文本完全一致; - 使用
openssl asn1parse解析显示,两者的ASN.1结构(盐值、密文段)存在差异; - 第三方PAC服务接受original.key,但拒绝new.key。
疑问
PEM转DER的过程是否遗漏了关键步骤?是否需要设置pRSAKey的特定字段才能还原出与原文件完全一致的DER格式私钥?
内容的提问来源于stack exchange,提问作者alvaroc
相关产品推荐
相关产品推荐

