注:TLCP协议除IBC参数外,数字证书格式均要求为 X.509格式,数字证书格式参见 《GMT 0015-2012 基于SM2密码算法的数字证书格式》,其中服务端证书为“服务器证书”。
TLCP协议以CS(Client and Server)的架构实现通信:
区别于TLS协议,TLCP协议要求服务端需要使用2对非对称密钥对以及2张证书,它们分别是:
我们将签名密钥对与加密密钥对统称为 服务端密钥 。
数字证书要求:
1.3.6.1.5.5.7.3.1
)**若服务端开启了对客户端的身份认证,那么此时客户端将会传输它的认证证书以及认证密钥的签名值供服务端验证(详见 GB/T 38636 6.4.4 握手协议总览),为了有效验证客户端证书的有效性,服务端需要预先导入客户端的根证书列表,否则无法验证客户端证书有效导致握手终止。
根据服务端对客户端认证要求的不同,客户端在握手流程具有不同表现,目前服务端对客户端认证方式支持:
若服务端开启了握手要求客户端身份认证,那么客户端必须具有客户端密钥,并且在握手过程中将会发送客户端证书消息(Client Certificate)、客户端证书验证消息(Certificate Verify)
为了与服务端的签名证书与签名密钥对区别,通常使用客户端认证密钥对、认证证书 来称呼客户端签名密钥对及证书。
按照握手协议在服务端发送了服务端的证书列表(两张证书,签名证书、加密证书),那么客户端应验证分别两张证书的有效性,因此* *客户端需要预先导入服务端根证书列表**,否则无法验证服务端证书有效导致握手终止。
数字证书要求:
1.3.6.1.5.5.7.3.2
)**注:TLCP协议区别TLS协议,TLCP协议的服务端证书消息中为2张证书,按顺序分别为签名证书、加密证书。
目前Go TLCP通过emmansun/gmsm
的smx.509
模块,目前数字证书解析支持数字证书的PEM格式,您可以通过下面这个方式解析证书:
cert, err := smx509.ParseCertificatePEM([]byte(ROOT_PEM))
if err != nil {
panic(err)
}
GoTLCP修改自golang 1.19
的crypto/tls
,采用了tlcp.Certificate
的对象作为证书和密钥证书密钥对,tlcp.Certificate
结构下:
package tlcp
// Certificate 数字证书及密钥对
type Certificate struct {
Certificate [][]byte // 数字证书DER二进制编码数组
PrivateKey crypto.PrivateKey // 密钥对接口
}
您需要提供以下参数构造该对象:
crypto.PrivateKey
接口的都可以作为密钥对。关于 Certificate [][]byte
您可以通过,smx509.Certificate
对象的Raw
字段获取数字证书的DER编码,如下:
cert, _ := smx509.ParseCertificatePEM(CERT_PEM_CODE)
var certKey = tlcp.Certificate{}
certKey.Certificate = [][]byte{cert.Raw}
警告:请在确保密钥符合国家密码管理要求前提下,管理使用非对称密钥对。
GoTLCP根据密钥的用途,要求密钥的实现相应的Go标准接口:
crypto.Signer
crypto.Decrypter
相关接口定义如下:
package crypto
type Signer interface {
// Public 公钥
Public() PublicKey
// Sign 数字签名
Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)
}
type Decrypter interface {
// Public 公钥
Public() PublicKey
// Decrypt 私钥解密
Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error)
}
关于
crypto.Signer
、crypto.Decrypter
更多信息见 src/crypto/crypto.go
服务端密钥对:
crypto.Signer
crypto.Decrypter
客户端密钥对:
crypto.Signer
通过上述接口抽象与解耦,可以实现与SDF、SKF接口对接,通过密码硬件设备实现相应的密码功能。
若您正处于测试与调试阶段,您可以实现目前GoTLCP提供的接口来实现证书、密钥的解析,构造tlcp.Certificate
。
目前仅支持对 X509 DER PEM编码的证书证书 与 PKCS#8格式(未加密)PEM编码的SM2密钥解析,您可以按照下面方式解析密钥对及证书:
keycert, err := tlcp.LoadX509KeyPair(certFile, keyFile)
if err != nil {
panic(err)
}
或使用tlcp.X509KeyPair
从PEM的字节码中解析。
GoTLCP在工作过程中需要管理使用以下密钥:
密钥名称 | 置零时机 | 说明 |
---|---|---|
预主密钥(pre_master_secret) | 主密钥生成后置零 | 双方协商生成的密钥素材,用于生成主密钥 |
主密钥(master_secret) | 握手成功后 | 由预主密钥、客户端随机数、服务端随机数、产量字符串,经计算的密钥素材,用于生成工作密钥 |
工作密钥(work_secrets) | 连接断开 | 包括数据加密密钥和校验密钥。其中数据加密密钥用于数据的加密和解密,校验密钥用于数据的完整性计算和校验。 |
由于Go语言的垃圾回收机制,依靠Go语言本身无法实现对内存的置零操作,因此GoTLCP设计了用于实现的内存置零的 setZero 方法:
该方法可以有效防止编译器优化掉内存置零操作,确保密钥数据从内存中清除。