使用openssl创建自签名证书以及单向认证程序实例

生成CA证书

创建CA私钥

openssl genrsa -out ca.key 2048

请求CA证书

openssl req -new -sha256 -key ca.key -out ca.csr -subj "/C=CN/O=Private/CN=CA"

C-----国家(Country Name)
ST----省份(State or Province Name)
L----城市(Locality Name)
O----公司(Organization Name)
OU----部门(Organizational Unit Name)
CN----产品名(Common Name)
emailAddress----邮箱(Email Address)

自签署CA证书

openssl x509 -req -days 36500 -sha256 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.cer

生成服务器证书

创建服务器私钥

openssl genrsa -out server.key 2048

请求服务器证书

openssl req -new -sha256 -key server.key -out server.csr -subj "/C=CN/CN=SERVER" -addext "subjectAltName=DNS:www.mylocal.com,DNS:localhost"

使用CA证书签署服务器证书

openssl x509 -req -days 36500 -sha256 -extensions v3_req -extfile openssl.cnf -CA  ca.cer -CAkey ca.key  -CAserial ca.srl  -CAcreateserial -in server.csr -out server.cer
cat openssl.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.mylocal.com
DNS.2 = localhost

如果不加-extfile openssl.cnf,会报Warning: ignoring -extensions option without -extfile; 并且签署的证书没有subjectAltName部分。

测试证书

服务器

openssl s_server -CAfile ca.cer -cert server.cer -key server.key -accept 127.0.0.1:443

客户端

openssl s_client -CAfile ca.cer -connect 127.0.0.1:443

查看证书内容命令

openssl req -text -noout -in server.csr
openssl x509 -text -noout -in server.cer

服务器程序

package main
import (
    "bufio"
    "crypto/tls"
    "log"
    "net"
)
func main() {
    cert, err := tls.LoadX509KeyPair("server.cer", "server.key")
    if err != nil {
        log.Println(err)
        return
    }
    config := &tls.Config{Certificates: []tls.Certificate{cert}}
    ln, err := tls.Listen("tcp", "www.mylocal.com:443", config)
    if err != nil {
        log.Println(err)
        return
    }
    defer ln.Close()
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Println(err)
            continue
        }
        go handleConn(conn)
    }
}
func handleConn(conn net.Conn) {
    defer conn.Close()
    r := bufio.NewReader(conn)
    for {
        msg, err := r.ReadString('\n')
        if err != nil {
            log.Println(err)
            return
        }
        log.Println("receive: " + msg)
        n, err := conn.Write([]byte("world\n"))
        if err != nil {
            log.Println(n, err)
            return
        }
    }
}

客户端程序

package main

import (
        "crypto/tls"
        "crypto/x509"
        "log"
)

func printPeerCrt(conn *tls.Conn) {
        certChain := conn.ConnectionState().PeerCertificates
        for i, cert := range certChain {
                log.Println(i)
                log.Println("Issuer: ", cert.Issuer)
                log.Println("Subject: ",cert.Subject)
                log.Println("Version: ", cert.Version)
                log.Println("NotAfter: ", cert.NotAfter)
                log.Println("DNS names: ", cert.DNSNames)
                log.Println("")
        }
}

func main() {
//ca.cer或者server.cer的客户端验证,golang 的tls包两者都支持。
        const rootCA = `
-----BEGIN CERTIFICATE-----
MIIC4TCCAckCFH8i2PdtFFFQuOWwuImuPTT1fzE/MA0GCSqGSIb3DQEBCwUAMCwx
CzAJBgNVBAYTAkNOMRAwDgYDVQQKDAdQcml2YXRlMQswCQYDVQQDDAJDQTAgFw0y
NDEwMDkwNjAwNThaGA8yMTI0MDkxNTA2MDA1OFowLDELMAkGA1UEBhMCQ04xEDAO
BgNVBAoMB1ByaXZhdGUxCzAJBgNVBAMMAkNBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAxlwyx9VJsX/IdaLgKuuJpjKGBfMa42JLIzSoZMIA08PdGJAg
UD4uhut9ikuUZLC60qRko75RvnpvV8Rgj9b9l1HdlQ8bKq7FcumfCN9UN9DgbMHv
d6zLCFirZecUWejN+jxCJtd65uqb3KpjCaEcPf2VYy7as0wudJ0SWqXBWx8AuSiQ
7wJCTX+CnnoEK7HCY3/XFe0OG7qRiM47LiAPmXvOncAXkcYmM9+IHjVmPRpm74Nf
USPElWOC88QDTP+Qfuhcrzka4r+RFuoNFlXlkNzDlpB51bt5rAfw+VcR30CT3qD7
25EvVBX7XIU9Yer288eVX1dqmlqijrgK99p6fwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQBbR2+TxtspFu+e0/WwJDO4lzHxRceiVYVg4Pf7llLM219bcSh7horhmK/W
3CVsPnk4VZF5XPwyacMQUsZT3G9qK4g+Psdl9FLsgEiqFSjnKvvRsH9z2w48G0ef
6DV4LdsR9Z3W0S2gD2To1E65Un5lM8Pxfi0E04wFB3j+k9LLMuX4sxGRyJjnzWsU
opP7bY/YMG2RdyDOflEW4dbf65rm3trZBQPihxeQsD3Ogcqjuq4bFLtRkIimjSXU
7RRKDrKV/FH91ZH2TJxZ7Ut6xJWb31QvER6Fj05Z7wTEfYlV6tU/DyY6qPWx+WGU
h+n4/JKJ5qpEYcZmElGklMqIIVfM
-----END CERTIFICATE-----`

        const rootServer = `
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIUXbyWdGLu10nO9c25tOBnn+3KBC4wDQYJKoZIhvcNAQEL
BQAwLDELMAkGA1UEBhMCQ04xEDAOBgNVBAoMB1ByaXZhdGUxCzAJBgNVBAMMAkNB
MCAXDTI0MTAwOTA2MDA1OVoYDzIxMjQwOTE1MDYwMDU5WjAeMQswCQYDVQQGEwJD
TjEPMA0GA1UEAwwGU0VSVkVSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAzVI0yWfET+QGXUF+tGcxGkTA/8MpuKKC38EjglomkK+HKuQy1wIfJmdcLYfF
0RW3459zm6FLUd1ol2vw0h7lbYoGwdbWKHXVNeZpTD6enN7QxaNASamYfMTjCMvi
HDoLO51TxRnxZWQ5sfn5iKuVBgP2VBEz2gYQQPgZNa+VRLMraWEcB6ASDqNK/gbb
dVBRlA5pbyUnNvQPglvyEKxcN69OSVE6kMccXkk6EJrw/kjqScDI2NDTx8W+skLZ
uZxHujIWIuObVtN3NDxKGfjmrXbdWyIrNKXnww0GI8kCfqPPcL1MdRqDYW2Ds4F8
8ocTIej09aSQO+rkJVf1e7UeGwIDAQABo4GcMIGZMCUGA1UdEQQeMByCD3d3dy5t
eWxvY2FsLmNvbYIJbG9jYWxob3N0MB0GA1UdDgQWBBQDICO/gc5QbfqhqMJB9xdF
0JDvJjBRBgNVHSMESjBIoTCkLjAsMQswCQYDVQQGEwJDTjEQMA4GA1UECgwHUHJp
dmF0ZTELMAkGA1UEAwwCQ0GCFH8i2PdtFFFQuOWwuImuPTT1fzE/MA0GCSqGSIb3
DQEBCwUAA4IBAQC14Vz+tuMfC9KbzzhSxIrcuZ3Y+eGlo0nyt7Lnk4dZRMVKVbjW
m4rUXs8vxJWBN+EzqcNtjpUTVFjskzVC/Zk8Iqv1UHoYmlv0yr0wUWDaBWJ/yMlB
leO0rRzBOnfkKCAJFSDczfiyqOf77ehaO5YS0Oce9zzv+cPfehywg5RBlFKfAUdg
g3s8ZyJCam9XIvXyFq2e6zwMJkCR6oYJECOKxvonwq02VydAtXAf6srHY7AJsa47
5+gmwHAn0nv/Ga/QfkVQwswwFTTgNIEdCiM6j4yH1YvSalV5pOEjIFwR+vYlMfct
39OVgzcZObP9NYnkB0A8EAjGRlzbmTn4VZUE
-----END CERTIFICATE-----`
        roots := x509.NewCertPool()
        ok := roots.AppendCertsFromPEM([]byte(rootServer))
        //ok := roots.AppendCertsFromPEM([]byte(rootCA))
        if !ok {
                panic("failed to parse root certificate")
        }
        //regard to IP SANs
        //conn, err := tls.Dial("tcp", "127.0.0.1:443",
        //regard to SANs
        //conn, err := tls.Dial("tcp", "www.mylocal.com:443",
        conn, err := tls.Dial("tcp", "localhost:443",
                &tls.Config{InsecureSkipVerify: false,
                        RootCAs: roots,
                        MaxVersion: tls.VersionTLS12,
                        })
        if err != nil {
                log.Fatal(err)
        }
        printPeerCrt(conn)
        defer conn.Close()
        _, err = conn.Write([]byte("hello\n"))
        if err != nil {
                log.Fatal(err)
        }
        buf := make([]byte, 1000)
        n, err := conn.Read(buf)
        if err != nil {
                log.Fatal(err)
        }
        log.Println("receive: " + string(buf[:n]))
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值