解析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证书
//先解码,再解析
certBlock, restBlock := pem.Decode([]byte(pemStr))
if certBlock == nil {
fmt.Println(err)
return
}
certBody, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
fmt.Println(err)
return
}
测试的时候直接传PEM的数据解码不成功,形式如下
通过读文件或者pem数据中的换行换成\n形式才成功
解析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证书的操作后续再做进一步介绍
版权声明:本文为a137748099原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。