解析PEM证书链
//递归解码,存到tls.Certificate中
func DecodeChain(chainByteArray []byte, certBuf *tls.Certificate) {
certDERBlock, restPEMBlock := pem.Decode(chainByteArray)
if certDERBlock == nil {
return
certBuf.Certificate = append(certBuf.Certificate, certDERBlock.Bytes)
if len(restPEMBlock) != 0 {
DecodeChain(restPEMBlock, certBuf)
chainsTmp, err := ioutil.ReadFile("chains.pem")
if err != nil {
fmt.Println("Read file failed")
return
var chainList tls.Certificate
DecodeChain(chainsTmp, &chainList)
for _, cert := range chainList.Certificate {
certTmp, _ := x509.ParseCertificate(cert)
DER转PEM
func CertDerToPem(derData []byte) []byte {
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: derData,
return pem.EncodeToMemory(block)
usrCert, error := getCertBody("C:/Users/xxx/Desktop/baidu.cer")
middleCert, error := getCertBody("C:/Users/xxx/Desktop/GlobalSign-G2.cer")
// rootCert, error := getCertBody("C:/Users/xxx/Desktop/GlobalSign-root.cer")
if error != nil {
return
fmt.Printf("%x", usrCert.SerialNumber)
roots := x509.NewCertPool()
roots.AddCert(middleCert)
// roots.AddCert(rootCert)
opts := x509.VerifyOptions{
DNSName: "www.baidu.com",
Intermediates: roots,
CurrentTime: time.Now(),
chains, error := usrCert.Verify(opts)
if error != nil {
fmt.Println("verify error", error.Error())
ca证书只有中级根也能够正常验证,验证成功会返回完整的证书链
解析x509证书项
serialNumber := fmt.Sprintf("%x", certBody.SerialNumber)
signAlg := certBody.SignatureAlgorithm.String()
certBody.NotBefore.Format("2006-01-02 15:04:05")
certBody.NotAfter.Format("2006-01-02 15:04:05")
//获取算法密钥长度
func GetPubKeyLen(pub interface{}) (int, error) {
var pubKeyLen int
var err error
switch pub := pub.(type) {
case *rsa.PublicKey:
pubKeyLen = pub.N.BitLen()
case *ecdsa.PublicKey:
pubKeyLen = pub.X.BitLen()
case ed25519.PublicKey:
pubKeyLen = 8 * len(pub)
default:
pubKeyLen = 0
err = errors.New("PubKey Type Error")
return pubKeyLen, err
keyLen, ok := GetPubKeyLen(certBody.PublicKey)
if ok == nil {
encryptAlg := certBody.PublicKeyAlgorithm.String() + fmt.Sprintf("(%d bits)", keyLen)
//二进制值
publicKeyDer, _ = x509.MarshalPKIXPublicKey(certBody.PublicKey)
//转成16进制
hexString := hex.EncodeToString(publicKeyDer)
sha-1指纹
h := sha1.New()
h.Write(certBody.Raw)
s := hex.EncodeToString(h.Sum(nil))
s1 := strings.ToUpper(s)
sha256指纹
h256 := sha256.New()
h256.Write(certBody.Raw)
s256 := hex.EncodeToString(h256.Sum(nil))
ss := strings.ToUpper(s256)
certInfo.Sha256Fp = ss
扩展密钥用法
func ExtKeyUsageString(arr []x509.ExtKeyUsage) []string {
var extArr []string
for i := 0; i < len(arr); i++ {
ext := arr[i]
// var extStr string
switch ext {
case x509.ExtKeyUsageServerAuth:
extArr = append(extArr, "Server Auth")
case x509.ExtKeyUsageClientAuth:
extArr = append(extArr, "Client Auth")
case x509.ExtKeyUsageCodeSigning:
extArr = append(extArr, "Code Signing")
case x509.ExtKeyUsageEmailProtection:
extArr = append(extArr, "Email Protection")
case x509.ExtKeyUsageIPSECEndSystem:
extArr = append(extArr, "IPSEC End System")
case x509.ExtKeyUsageIPSECTunnel:
extArr = append(extArr, "IPSEC Tunnel")
case x509.ExtKeyUsageIPSECUser:
extArr = append(extArr, "IPSEC User")
case x509.ExtKeyUsageTimeStamping:
extArr = append(extArr, "TimeStamping")
case x509.ExtKeyUsageOCSPSigning:
extArr = append(extArr, "OCSP Signing")
case x509.ExtKeyUsageMicrosoftServerGatedCrypto:
extArr = append(extArr, "Microsoft Server Gated Crypto")
case x509.ExtKeyUsageNetscapeServerGatedCrypto:
extArr = append(extArr, "Netscape Server Gated Crypto")
case x509.ExtKeyUsageMicrosoftCommercialCodeSigning:
extArr = append(extArr, "Microsoft Commercial Code Signing")
case x509.ExtKeyUsageMicrosoftKernelCodeSigning:
extArr = append(extArr, "Microsoft Kernel Code Signing")
return extArr
extKeyUsageList := ExtKeyUsageString(certBody.ExtKeyUsage)
ocsp地址
ocspUrl := certBody.OCSPServer
颁发者机构信息访问地址
caUrl := certBody.IssuingCertificateURL
crl地址
crlUrl := certBody.CRLDistributionPoints
其他扩展项
exts := certBody.Extensions
for i := 0; i < len(exts); i++ {
ext := exts[i]
//证书透明sct
if ext.Id.String() == "1.3.6.1.4.1.11129.2.4.2" {
certSct := ext.Value
x509库解析证书目前无法解析SM2证书,SM2证书验证也验不了,关于SM2证书的操作后续再做进一步介绍
解析DER证书 //读der证书 derTmp, err := ioutil.ReadFile("123.cer") if err != nil { fmt.Println("Read file failed") return } //调用x509的接口 certBodyTmp, err := x509.ParseCertificate(derTmp) if err != nil { fmt.Println(err) return }解析PEM证书
ASN.1是一种标记语言,基于这种标记语言可以进行数据表示、编码、传输和解码
DER是一种属于ASN.1的编码格式
X.509证书是一种密码学中的公钥数字证书标准,规定了一个数字证书需要哪些信息,而这些信息的编码格式是可以采用ASN.1中的DER编码格式
在go语言提供的系统包中包含了大量和数字证书有关的方法。在这些方法中就有私钥生成的方法、私钥解析的方法、证书请求生成的方法、证书生成的方法等等。通过这些方法应该能够实现和openssl命令类似的功能。
仿照openssl生成证书的流程(从私钥的生成—>证书请求的生成—>证书的生成)用go语言进行模拟。
私钥的生成
在go的x509包下有go定义...
model , err := Unmarshal ([] byte ( data ))
// supply additional variables
model . SetProperty ( "a.b" , "y" )
version , err := model . Get ( "version" )
// version is xx.y.z
pom.xml :
<? xml version = " 1.
在密码学中,X.509是公钥证书的格式标准,在许多互联网协议中得到应用。X.509对公钥证书的格式,撤销证书列表(CRLs),证书验证路径算法等进行了规定。一个X.509证书中包含了其版本号,证书序列号,签名算法,签发者,证书主体,有效期,公钥,公钥密钥等信息。证书中的信息使用 ASN.1进行编码,ASN.1中数据以tag,长度,值的方式进行编码。证书的基本结构在RFC 5280中4.1节进行了如下的规定:
二、读取 X.509证书
提交的程序中使用 Go 语言编写读取 X.509的程序,调用了 Go 语言
本文借助于第三方库github.com/tjfoc/gmsm/sm2
首先看一下支付宝java版sdk解析思路:
支付宝根证书有四部分构成,但不是说每一部分都能用的到,根据java版sdk来看,只有oid值以1.2.840.11359.1.1开头的参与根证书序列号的拼接
golang代码:
func GetCertRootSn(certPath ...
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device.
前段时间因工作需要,了解到在Github上已经有人实现了用JavaScript来写签名和验签,支持RSA、ECC、DSA等算法,还能解析X.509证书,一时觉得JavaScript是无比强大。后面就研究了下JavaScript版的ECC算法签名验证,自己再扩展实现了SM2国密算法的签名验证。
基于现有已实现的C#版SM2国密算法的签名验证,再结合原来JavaScript的ECC算法,使用Java
本篇文章中,将描述如何使用go创建CA,并使用CA签署证书。在使用openssl创建证书时,遵循的步骤是 创建秘钥 > 创建CA > 生成要颁发证书的秘钥 > 使用CA签发证书。这种步骤,那么我们现在就来尝试下。首先,会从将从创建 CA 开始。CA 会被用来签署其他证书
接下来需要对证书生成公钥和私钥
然后生成证书:
我们看到的证书内容是PEM编码后的,现在我们有了生成的证书,我们将其进行 PEM 编码以供以后使用:
证书的 与CA的 属性有稍微不同,需要进行一些修改
为该证书创建私钥和公钥
Go 语言支持多种方式解析 XML,其中最常用的是内置的 encoding/xml 包。该包提供了简单易用的 API,可以快速有效地解析 XML 文档。
下面是一个简单的示例:
package main
import (
"encoding/xml"
"fmt"
type Person struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name"`
Age int `xml:"age"`
func main() {
xmlFile, err := os.Open("person.xml")
if err != nil {
fmt.Println("Error opening XML file:", err)
return
defer xmlFile.Close()
var person Person
decoder := xml.NewDecoder(xmlFile)
err = decoder.Decode(&person)
if err != nil {
fmt.Println("Error decoding XML:", err)
return
fmt.Println("Person:", person)
这段代码将解析如下所示的 XML 文档:
<person>
<name>John Doe</name>
<age>30</age>
</person>
在上面的代码中,我们定义了一个 Person 结构体,并使用 xml 包中的 xml.Name 和 xml 标签标记指定 XML 文档中字段的名称。然后,我们使用 os 包的 os.Open() 函数打开 XML 文件,并使用 xml.NewDecoder() 函数创建一个解码器。最后,我们调用 decoder.Decode() 函数解码 XML 文档,并将解析出的内容存储在 person 结构体中。
【报错】Qt报错 error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”
qq_45894471:
【Qt】QGraphicsItem无法触发mouseMoveEvent问题
【Qt】QGraphicsItem无法触发mouseMoveEvent问题
oeluj:
【Qt】利用QAxObject实现word转pdf
【Qt】利用QAxObject实现word转pdf