GO (国密,标准Https) 单向,双向认证Demo

本文详细介绍了如何使用开源项目tjfoc/gmsm进行国密通信,包括生成私钥、证书及解决常见问题,提供了生成CA、服务器签名和加密证书的步骤,并展示了HTTP与GMSSL服务器客户端的连接示例。

最近使用开源项目tjfoc/gmsm 做国密研究,由于他没有具体说怎么生成证书的,期间对于生成他对应的国密证书做了些研究,踩了一些坑

他对国密通信做的demo主要在websvr目录下

下面主要说下生成国密证书步骤

1. 需要装gmssl , 具体编译参见上一篇文章

2. 使用gmssl ecparam -genkey -name sm2p256v1 -noout -out ${OUTPUT}/${name}.key 生成的私钥在他的go代码 gmtls.LoadX509KeyPair 方法会报错,经过研究可以使用x509目录下的go生成私钥

所以使用x509目录下的生成私钥代码

func createPrvateKey(s string)  {
	priv, err := sm2.GenerateKey(nil) // 生成密钥对
	if err != nil {
		return
	}
	privPem, err := WritePrivateKeyToPem(priv, nil) // 生成密钥文件
	fmt.Printf("privateKey=%s",privPem)
	if err != nil {
		return
	}
	os.Remove(s)
	os.WriteFile(s,privPem,0666)
}

其他部分还是使用gmssl生成

3. 开始生成的证书会报keyUsage相关错误,以server签名证书为例

使用./openssl.cnf -extensions v3_req 参数,在openssl.cnf中

 server加密证书

-extfile ./openssl.cnf -extensions v3enc_req

4. 如果遇到 x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs 解决: 解决参考

在openssl.cnf中

测试Demo代码

package main

import (
	"crypto/tls"
	"fmt"
	"github.com/tjfoc/gmsm/gmtls"
	"github.com/tjfoc/gmsm/x509"
	"io/ioutil"
	"log"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w,
		"王家荣")
}
func httpServerOne()  {
	http.HandleFunc("/", handler)
	err := http.ListenAndServeTLS(":50052", "./certs/standard_server_sign.cer",
		"./certs/standard_server_sign.key", nil)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("单项httpServer启动成功")
	}
}

func httpServerTwo() {
	config,err := newServerConfig()
	if err != nil {
		fmt.Println(err)
		return
	}
	http.HandleFunc("/", handler)
	s := &http.Server{
		Addr: ":50052",
		TLSConfig: config,
	}
	log.Fatal(s.ListenAndServeTLS("./certs/standard_server_sign.cer", "./certs/standard_server_sign.key"))
}

func httpClientOne()  {
	config,err := newClientConfig()
	if err != nil {
		fmt.Println(err)
		return
	}
	conn, err := tls.Dial("tcp", "127.0.0.1:50052", config)
	if err != nil {
		fmt.Printf("%s\r\n",err)
		return
	}
	defer conn.Close()

	req := []byte("GET / HTTP/1.1\r\n" +
		"Host: 127.0.0.1\r\n" +
		"Connection: close\r\n\r\n")
	_, _ = conn.Write(req)
	buff := make([]byte, 1024)
	for {
		n, _ := conn.Read(buff)
		if n <= 0 {
			break
		} else {
			fmt.Printf("收到回应[%s]\r\n", buff[0:n])
		}
	}
	fmt.Println("标准HTTPS 单向认证通过")
}
func httpClientTwo()  {
	config,err := newClientConfig()
	if err != nil {
		fmt.Println(err)
		return
	}
	conn, err := tls.Dial("tcp", "127.0.0.1:50052", config)
	if err != nil {
		fmt.Printf("%s\r\n",err)
		return
	}
	defer conn.Close()

	req := []byte("GET / HTTP/1.1\r\n" +
		"Host: 127.0.0.1\r\n" +
		"Connection: close\r\n\r\n")
	_, _ = conn.Write(req)
	buff := make([]byte, 1024)
	for {
		n, _ := conn.Read(buff)
		if n <= 0 {
			break
		} else {
			fmt.Printf("收到回应[%s]\r\n", buff[0:n])
		}
	}
	fmt.Println("标准HTTPS 双向认证通过")
}


func gmServerTwo() {
	sigCert, err := gmtls.LoadX509KeyPair(
		"./certs/server_sign.cer",
		"./certs/server_sign.key")
	if err != nil {
		fmt.Println(err)
	}
	encCert, err := gmtls.LoadX509KeyPair(
		"./certs/server_encode.cer",
		"./certs/server_encode.key")
	if err != nil {
		fmt.Println(err)
	}
	certPool := x509.NewCertPool()
	cacert, err := ioutil.ReadFile("./certs/ca.cer")
	if err != nil {
		fmt.Println(err)
	}
	certPool.AppendCertsFromPEM(cacert)
	config := &gmtls.Config{
		GMSupport:    &gmtls.GMSupport{},
		Certificates: []gmtls.Certificate{sigCert, encCert},
		ClientAuth:   gmtls.RequireAndVerifyClientCert,
		ClientCAs:    certPool,
	}
	if err != nil {
		fmt.Println(err)
	}
	ln, err := gmtls.Listen("tcp", ":50052", config)
	if err != nil {
		fmt.Println(err)
	}
	defer ln.Close()
	serveMux := http.NewServeMux()
	serveMux.HandleFunc("/", handler)
	fmt.Println(">> HTTP :50055 [GMSSL] Client Auth running...")
	err = http.Serve(ln, serveMux)
	if err != nil {
		fmt.Println(err)
	}
}

func gmServerOne() {
	sigCert, err := gmtls.LoadX509KeyPair(
		"./certs/server_sign.cer",
		"./certs/server_sign.key")
	if err != nil {
		fmt.Println(err)
	}
	encCert, err := gmtls.LoadX509KeyPair(
		"./certs/server_encode.cer",
		"./certs/server_encode.key")
	if err != nil {
		fmt.Println(err)
	}
	config := &gmtls.Co
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值