支付宝RSA2公钥证书生成
前言
支付宝新的转账接口例如转账“alipay.fund.trans.uni.transfer”接口已经在推新的公钥证书模式,由支付宝作为CA帮我们的公钥做签发这样可以在与支付宝通讯时防止通信内容内容被篡改,因此安全性得到了提升,双向通信都需要做验证,但是我们通常在测试情况下需要自身mock支付宝的返回,以此验证各种情况下程序的正确性,生产可以直接下载支付宝CA签名好的公钥,这样就需要我们类似于支付宝做一个自签名的公钥证书,自签发后提供给我们的测试程序使用,同时私钥由mock程序持有来模拟支付宝服务端做签名,下面将分别介绍两种借助支付宝开放平台开发助手和openssl来生成公钥证书,并且第三节提供了测试代码可以用于测试公私钥
支付宝开放平台开发助手生成
上述文档可以指导我们配置生产证书,但是要用它做mock还需要自签名拿到公钥证书,进行下面步骤
- 生成秘钥→RSA2→PCKS8点击生成秘钥 获得:应用公钥 2048.txt、应用私钥 2048.txt
- 获取CSR文件->点击获取→RSA2→ PKCS8填一下参数点击生成CSR文件:获得xx.scr文件(这里演示代指为test.com.csr),scr是签名请求文件
- 第一步生成的:应用私钥 2048.txt是PKCS8格式的私钥,签名需要PKCS1格式的私钥,可以用工具中的格式转换→转PKCS1做转换转换完成后得到PKCS1文本保存到本地,(此处演示使用pri_pkcs1.crt命名)
- 注意3步骤得到的PKCS1文本需要按照65字符换行且加上头尾,头:-----BEGIN RSA PRIVATE KEY----- 尾:-----END RSA PRIVATE KEY-----
- 使用openssl做自签名,命令:openssl x509 -req -in test.com.csr -out testpem.crt -signkey pri_pkcs1.crt -days 3650
- 这样我们就模拟CA为我们的公钥做了签名得到的testpem.crt证书就可以作为公钥证书使用了,加签、加密看要求是PKCS1可以用pri_pkcs1.crt、或者用PKCS8可用应用私钥 2048.txt(加上头尾-----BEGIN PRIVATE KEY-----、-----END PRIVATE KEY-----) (可以改个名如pri_pkcs8.crt )
使用openssl生成
通常mac电脑自带openssl无需额外安装
- 使用命令:openssl genrsa -out server.crt 2048 获得PKCS1证书
- 使用命令:openssl pkcs8 -topk8
-inform PEM -in server.crt -outform PEM -nocrypt 可以生成不带密码的PKCS8格式的证书,可以保持为文件,这里演示保存为testprivate_pkcs8.key - 使用命令:openssl req -new -key server.crt -out server.csr
并根据提示输入证书信息,得到包含自身信息的证书请求文件用于请求CA为自己的公钥做签名,最后一个是密码不需要直接回车跳过 - 使用命令:openssl x509 -req -in server.csr -out server_pem.crt -signkey
server.crt -days
3650,这样可以用自己的私钥代替CA为自己做签名,证书有效期10年足够使用了,注意这个不是受信任的CA签发的证书所以无法在生产环境受信任但是测试环境没问题 - 最后公钥证书为server_pem.crt、私钥按格式分别为:
server.crt(pkcs1)和3中生成的testprivate_pkcs8.key
测试代码(golang)
下附测试证书
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
)
func main() {
// 待签名参数集
params := "123123123,模拟待签名参数"
// 从文件加载公钥证书
err := LoadPublicCertFromFile("test_pub.pem")
if err != nil {
fmt.Println("LoadPublicCertFromFile, err=", err)
return
}
// 加载私钥
err = LoadPrivateCertFromFile("test_pri.crt")
if err != nil {
fmt.Println("LoadPrivateCertFromFile, err=", err)
return
}
jsonData, err := json.Marshal(params)
if err