Golang ssl 证书 双向认证 keytool

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 源代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352