最近使用开源项目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
国密证书生成与GMSSL实战教程:从零到完整示例

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

被折叠的 条评论
为什么被折叠?



