美文网首页
Golang ssl 证书 双向认证 keytool

Golang ssl 证书 双向认证 keytool

作者: VIL凌霄 | 来源:发表于2019-05-15 14:35 被阅读0次

    openssl 与 keytool 都是证书的相关工具。但是两者使用方法各有不同。

    openssl 使用方法

    第一步、生成根证书:

    openssl genrsa -out ca.key 2048
    openssl req -x509 -new -nodes -key ca.key -days 3650 -out ca.crt
    

    或者直接使用下面命令生成两个 crt 和 key

    openssl req  -x509 -new -nodes -keyout ca.key -out  ca.crt -days 3650
    

    参数

     -nodes: 不使用密码
    

    第二步、生成服务端证书:

    # server.key 为私钥
    openssl genrsa -out server.key 2048
    #这里的/cn是必须添加的 是服务端的域名或者是etc/hosts中的ip别名 也可以是使用*
    openssl req -new -key server.key -subj "/CN=bgi_bc" -out server.csr
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
    

    第三步、生成客户端证书:

    这一步与第二部相同,只是一个是用于服务端,一个是用于客户端使用

    opensslgenrsa -out client.key 2048
    # /cn是服务端的域名 或者是etc/hosts中的ip别名 也可以是使用*
    openssl req -new -key client.key -subj "/CN=*" -out client.csr
    openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial  -out client.crt -days 3650
    

    keytool 使用方法

    keytool 是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务。
    keystore:keytool将密钥和证书存在一个称为keystore的文件中。
    在keystore包含两种数据:

    • 密钥实体——密钥(secret key)又或者是私钥和配对密钥(非对称加密)
    • 可信任的证书实体——只包含公钥

    Alias(别名):每个keystore都关联这一个独一无二的alias,通常不区分大小写。
    keystore存储位置:在没有制定生成位置的情况下,keystore会存到用户的系统默认目录。

    keytool 生成证书的命令

    1、生成证书,存储到 jks 文件中

    keytool -genkey -alias [这里是证书别名] -keyalg RSA -keystore [这里写证书的存储文件和位置格式为jks] -validity [这里填有效天数] -keysize 2048
    

    2、查看存储文件中是否有证书

    keytool -list  -v -keystore [这里写证书的存储文件和位置格式为jks] 
    

    3、从 store 文件中导出证书,这里导出的是二进制证书

    keytool -export -alias  [这里是证书别名] -keystore selfsigned.jks -file [证书文件名] 
    

    4、如果要导出 pem 格式的十六进制证书需要加参数 -rfc

    keytool -export -alias  [这里是证书别名]  -keystore selfsigned.jks  -rfc -file  [证书文件名] 
    

    5、导出 pkcs12 客户端使用证书,导出的证书文件格式一般是 .p12 或者 .pfx 。

    keytool -alias [这里是证书别名] -v -importkeystore -srckeystore [这里是jks 证书存储文件] -srcstoretype jks -destkeystore [pfx 文件名] -deststoretype pkcs12
    

    6、导出私钥
    jks文件中的私钥不能直接得到,需要通过openssl将jks文件转换成pkcs12格式后再进行提取。

    openssl pkcs12 -in [pfx 类型的文件,或者p12类型文件] -nocerts -nodes -out [私钥文件]
    

    keytool 示例

    在生成证书过程中会需要设置密码,地区,公司组织等相关信息,自己使用是可以随便输入。

    keytool -genkey -alias ville -keyalg RSA -keystore ville.jks -validity 3650 -keysize 2048
    
    keytool -list  -v -keystore ville.jks
    
    keytool -export -alias ville -keystore ville.jks -rfc -file ville.crt 
    
    keytool -alias ville -v -importkeystore -srckeystore ville.jks -srcstoretype jks -destkeystore ville.pfx -deststoretype pkcs12
    
    openssl pkcs12 -in ville.pfx -nocerts -nodes -out ville.key
    

    生成如下文件:

    ville.jks  ville.key  ville.crt  ville.pfx
    

    其中 ville.key 是私钥,ville.crt 是提公钥, ville.pfx 是浏览器之类使用私钥的文件。

    Golang 证书认证

    在 openssl 和 key 中我们生成了 ca , server, client , ville 等相关的证书。

    使用场景

    我们这里假设 server 的证书是与 client 证书不是同一个地方生成的,他们是两个不同的公司提供的,ca 、client 和 ville 是属于客户端公司的证书,server 是属于服务端公司的证书。客户端公司需要请求服务端公司的接口。1、首先客户端公司要啊把他们的证书(公钥 .crt)提供给服务端公司,服务端公司要把客户端提供的证书加载到服务中,这样服务请求的时候就好校验客户端的请求。
    2、服务端公司也要把他们的服务证书(公钥 .crt)提供给客户公司,客户端公司要加载到客户端程序,用以校验请求到的数据是服务公司的。
    下面我们就以 Golang 的双向认证来做示例

    SSL 双向认证

    1、 服务端程序

    package main
    
    import (
        "crypto/tls"
        "crypto/x509"
        "fmt"
        "io"
        "io/ioutil"
        "log"
        "net/http"
    )
    
    type httpsHandler struct {
    }
    
    func addTrust(pool*x509.CertPool, path string) {
        aCrt, err := ioutil.ReadFile(path)
        if err!= nil {
            fmt.Println("ReadFile err:",err)
            return
        }
        pool.AppendCertsFromPEM(aCrt)
    
    }
    
    func (*httpsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "golang https server!!!")
    }
    
    func main() {
        pool := x509.NewCertPool()
    
        // 这里是加载客户端提供的证书,最好是加载客户端提供的根证书
        addTrust(pool,"../sslfile/ca.crt")
        addTrust(pool,"../sslfile/ville.crt")
    
        s := &http.Server{
            Addr:    ":8080",
            Handler: &httpsHandler{},
            TLSConfig: &tls.Config{
                ClientCAs:  pool,
                ClientAuth: tls.RequireAndVerifyClientCert,
            },
        }
            // 这里是加载 服务端自己的证书和私钥
        if err := s.ListenAndServeTLS("../sslfile/server.crt", "../sslfile/server.key"); err != nil {
            log.Fatal("ListenAndServeTLS err:", err)
        }
    }
    
    

    2、客户端

    package main
    
    import (
        "crypto/tls"
        "crypto/x509"
        "fmt"
        "io/ioutil"
        "net/http"
    )
    
    func addTrust(pool*x509.CertPool, path string) {
        aCrt, err := ioutil.ReadFile(path)
        if err!= nil {
            fmt.Println("ReadFile err:",err)
            return
        }
        pool.AppendCertsFromPEM(aCrt)
    }
    
    func TwoWaySSlCheck(){
        pool := x509.NewCertPool()
            // 这里加载服务端提供的证书,用于校验服务端返回的数据
        addTrust(pool,"../sslfile/server.crt")
            // 这里加载客户端自己的证书,要与提供给服务端的证书一致,不然服务端校验会不通过
        cliCrt, err := tls.LoadX509KeyPair("../sslfile/ville.crt", "../sslfile/ville.key")
        if err != nil {
            fmt.Println("Loadx509keypair err:", err)
            return
        }
        tr := &http.Transport{
            TLSClientConfig: &tls.Config{
                RootCAs:      pool,
                Certificates: []tls.Certificate{cliCrt},
            },
        }
        client := &http.Client{Transport: tr}
        resp, err := client.Get("https://localhost:8080")
        if err != nil {
            fmt.Println("Get error:", err)
            return
        }
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        fmt.Println(string(body))
    }
    
    func main(){
        TwoWaySSlCheck()
    }
    
    

    Github 源代码

    相关文章

      网友评论

          本文标题:Golang ssl 证书 双向认证 keytool

          本文链接:https://www.haomeiwen.com/subject/iawuaqtx.html