密码技术--证书及go语言生成自签证书

Posted Yuan_sr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了密码技术--证书及go语言生成自签证书相关的知识,希望对你有一定的参考价值。

证书类似身份证,里面记录了某人的姓名、年龄、地址等个人信息,还包括这个人的公钥(身份证号码),并由认证机构(类似派出所)进行数字签名后发放,只要我们看到该证书就可以知道认证机构认定了该公钥(身份证号码)的确属于此人,解决了数字签名中无法确认是谁的公钥的问题,该证书也叫公钥证书,简称证书。

go语言生成自签证书文件(RSA)

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "fmt"
    "math/big"
    "net"
    "os"
    "time"
)

func GenerateSelfSignedCertKey(keySize int, host string, alternateIPs []net.IP, alternateDNS []string) {
    //1.生成密钥对
    priv, err := rsa.GenerateKey(rand.Reader, keySize)
    if err != nil {
        panic(err)
    }
    //2.创建证书模板
    template := x509.Certificate{
        SerialNumber: big.NewInt(1), //该号码表示CA颁发的唯一序列号,在此使用一个数来代表
        Issuer:       pkix.Name{},
        Subject:      pkix.Name{CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix())},
        NotBefore:    time.Now(),
        NotAfter:     time.Now().Add(time.Hour * 24 * 365),
        KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, //表示该证书是用来做服务端认证的
        ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    }

    if ip := net.ParseIP(host); ip != nil {
        template.IPAddresses = append(template.IPAddresses, ip)
    }else {
        template.DNSNames = append(template.DNSNames, host)
    }

    template.IPAddresses = append(template.IPAddresses, alternateIPs...)
    template.DNSNames = append(template.DNSNames, alternateDNS...)

    //3.创建证书,这里第二个参数和第三个参数相同则表示该证书为自签证书,返回值为DER编码的证书
    certificate, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
    if err != nil {
        panic(err)
    }
    //4.将得到的证书放入pem.Block结构体中
    block := pem.Block{
        Type:    "CERTIFICATE",
        Headers: nil,
        Bytes:   certificate,
    }
    //5.通过pem编码并写入磁盘文件
    file, err := os.Create("ca.crt")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    pem.Encode(file, &block)

    //6.将私钥中的密钥对放入pem.Block结构体中
    block = pem.Block{
        Type:    "RSA PRIVATE KEY",
        Headers: nil,
        Bytes:   x509.MarshalPKCS1PrivateKey(priv),
    }
    //7.通过pem编码并写入磁盘文件
    file, err = os.Create("ca.key")
    if err != nil {
        panic(err)
    }
    pem.Encode(file, &block)
}

func main(){
    ip := []byte("127.0.0.1")
    alternateDNS := []string{"localhost"}
    GenerateSelfSignedCertKey(2048, "192.168.0.1", []net.IP{net.ParseIP(string(ip))}, alternateDNS)
}

查看证书内容

$ openssl x509 -in ca.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = 192.168.0.1@1622130200
        Validity
            Not Before: May 27 15:43:20 2021 GMT
            Not After : May 27 15:43:20 2022 GMT
        Subject: CN = 192.168.0.1@1622130200
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:b7:24:45:1e:1f:92:a4:19:2e:3b:76:5a:2a:39:
                    b6:e9:b4:a7:6f:fe:a6:a9:dd:e3:da:dd:69:46:16:
                    b8:d9:42:07:11:17:e8:61:b9:a8:54:07:bd:75:a1:
                    b5:78:82:78:48:66:ca:b6:d3:74:27:c4:06:2e:2c:
                    ec:69:bd:c4:2b:b3:79:6a:67:67:80:52:fc:5f:d9:
                    4e:32:fe:66:f7:d3:e1:8a:71:c3:0b:4b:ab:3c:e9:
                    e1:11:4c:7a:5a:b0:ff:87:4b:78:64:e1:ce:60:91:
                    71:aa:c7:d5:4e:4c:13:23:5c:25:f4:7a:aa:57:63:
                    77:ca:67:98:2e:5a:55:03:0d:7d:03:4b:1f:4a:31:
                    7a:fe:a0:16:71:d6:da:06:4e:0b:a8:b2:dd:3e:ee:
                    cc:08:ee:19:de:c3:a7:3b:71:2e:76:c2:40:1c:ba:
                    7c:b8:ed:d3:5e:b6:16:eb:88:56:a3:45:9c:a4:a4:
                    f5:2c:bb:d7:b6:38:34:2e:3d:48:25:ee:4e:ce:6c:
                    9c:ea:7f:fd:32:4f:7a:17:68:06:01:b5:bb:82:08:
                    bd:af:9e:39:fc:ca:4e:8e:15:48:ce:db:f7:72:c8:
                    4a:d9:71:97:27:f8:e7:2d:3a:af:00:0e:26:61:2f:
                    1c:13:27:f1:49:bf:80:b1:b9:41:14:2a:70:9e:32:
                    26:8b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Certificate Sign
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Subject Alternative Name:
                DNS:localhost, IP Address:192.168.0.1, IP Address:127.0.0.1
    Signature Algorithm: sha256WithRSAEncryption
         a6:27:5a:75:9c:b4:b8:1b:9a:f9:fa:96:3e:3d:16:73:93:6d:
         0a:d8:c1:ed:01:0c:09:0a:66:d8:f9:4d:e7:f4:93:ee:5c:c5:
         e2:3c:f5:5d:06:49:50:97:86:4f:fd:c5:f5:da:aa:bd:56:b7:
         0f:84:c3:18:c1:bb:4c:cb:78:14:90:13:2b:58:ae:fa:a9:2e:
         2d:2d:83:f3:24:83:4a:09:54:65:a4:f3:9f:a3:65:ce:43:a0:
         c4:43:f2:aa:7b:f3:f4:92:b0:6b:9b:75:ef:a3:43:cc:3d:51:
         25:ec:ac:ad:b8:65:61:70:5f:c8:b6:4b:57:05:2f:95:71:9c:
         e1:77:92:e1:e9:53:30:67:02:0b:c7:5c:f1:77:57:a7:09:37:
         07:e4:60:0d:f5:62:c3:9d:b6:4f:fc:36:4a:c3:d4:34:9a:60:
         da:9a:fd:dd:c0:3c:fd:cc:1f:06:59:a3:75:97:ad:e0:96:5e:
         39:a0:e9:a2:7b:d5:54:72:e0:54:f5:a3:57:9b:89:0b:0d:a0:
         fc:7c:6b:82:31:77:70:d3:a9:79:ed:db:2e:de:e7:16:a6:93:
         5c:9b:b8:cc:80:5b:d8:21:4a:62:a1:8a:ce:ce:19:86:d0:b3:
         fb:37:d2:74:75:3a:5d:9d:f7:0e:ff:79:0b:ae:9e:c7:df:88:
         f5:6b:b2:ae

go语言生成自签证书文件(ECDSA)

package main

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    //"crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "fmt"
    "math/big"
    "net"
    "os"
    "time"
)

func GenerateSelfSignedCertKey(keySize int, host string, alternateIPs []net.IP, alternateDNS []string) {
    //1.生成密钥对
    //priv, err := rsa.GenerateKey(rand.Reader, keySize)
    priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    if err != nil {
        panic(err)
    }
    //2.创建证书模板
    template := x509.Certificate{
        SerialNumber: big.NewInt(1), //该号码表示CA颁发的唯一序列号,在此使用一个数来代表
        Issuer:       pkix.Name{},
        Subject:      pkix.Name{CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix())},
        NotBefore:    time.Now(),
        NotAfter:     time.Now().Add(time.Hour * 24 * 365),
        KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, //表示该证书是用来做服务端认证的
        ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    }

    if ip := net.ParseIP(host); ip != nil {
        template.IPAddresses = append(template.IPAddresses, ip)
    }else {
        template.DNSNames = append(template.DNSNames, host)
    }

    template.IPAddresses = append(template.IPAddresses, alternateIPs...)
    template.DNSNames = append(template.DNSNames, alternateDNS...)

    //3.创建证书,这里第二个参数和第三个参数相同则表示该证书为自签证书,返回值为DER编码的证书
    certificate, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
    if err != nil {
        panic(err)
    }
    //4.将得到的证书放入pem.Block结构体中
    block := pem.Block{
        Type:    "CERTIFICATE",
        Headers: nil,
        Bytes:   certificate,
    }
    //5.通过pem编码并写入磁盘文件
    file, err := os.Create("ca.crt")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    pem.Encode(file, &block)

    ecpriv, err := x509.MarshalECPrivateKey(priv)
    if err != nil {
        panic(err)
    }

    //6.将私钥中的密钥对放入pem.Block结构体中
    block = pem.Block{
        Type:    "ECDSA PRIVATE KEY",
        Headers: nil,
        //Bytes:   x509.MarshalPKCS1PrivateKey(priv),
        Bytes:      ecpriv,
    }
    //7.通过pem编码并写入磁盘文件
    file, err = os.Create("ca.key")
    if err != nil {
        panic(err)
    }
    pem.Encode(file, &block)
}

func main(){
    ip := []byte("127.0.0.1")
    alternateDNS := []string{"localhost"}
    GenerateSelfSignedCertKey(2048, "192.168.0.1", []net.IP{net.ParseIP(string(ip))}, alternateDNS)
}

查看证书内容

$ openssl x509 -in ca.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN = 192.168.0.1@1622131917
        Validity
            Not Before: May 27 16:11:57 2021 GMT
            Not After : May 27 16:11:57 2022 GMT
        Subject: CN = 192.168.0.1@1622131917
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:7a:09:2f:ec:6b:5b:ed:c7:cd:c0:09:81:ba:d9:
                    e0:0d:7b:06:95:7d:34:7f:16:8b:57:32:e0:9a:49:
                    2c:fc:27:fe:a6:d2:1d:61:d5:aa:77:bf:77:9d:17:
                    dd:7a:22:9f:72:3a:d7:4d:19:f7:f7:1c:50:dd:e1:
                    2b:4c:7f:df:5e
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Certificate Sign
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Subject Alternative Name:
                DNS:localhost, IP Address:192.168.0.1, IP Address:127.0.0.1
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:20:34:8b:44:79:04:cf:15:bb:33:34:07:61:cc:74:
         b7:27:c5:a6:e9:01:9c:b1:bd:ee:29:52:b5:17:a2:7d:63:e0:
         02:21:00:da:f7:7c:1a:4f:25:d1:c3:b5:19:5d:93:06:fb:8b:
         41:5b:06:c8:6d:93:a0:b8:14:08:6a:90:1f:0b:84:39:d6

以上是关于密码技术--证书及go语言生成自签证书的主要内容,如果未能解决你的问题,请参考以下文章

linux中openssl生成证书和自签证书

Nginx使用自签证书配置SSL实现HTTPS访问

.NET 6学习笔记生成自签证书

企业为啥不能使用自签名SSL证书?

Nginx 配置生成自签证书

使用xca工具生成自签证书