From 2f586539d494c1b42e67d4a18472ec3cc8002e86 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Tue, 11 Jun 2024 17:42:19 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20CFCA=E4=BA=92=E6=93=8D=E4=BD=9C=E6=80=A7?= =?UTF-8?q?=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/cfca.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ pkcs7/encrypt.go | 2 +- 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 docs/cfca.md diff --git a/README.md b/README.md index 617ecb50..1cee9e33 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Go语言商用密码软件,简称**GMSM**,一个安全、高性能、易于 * [SM3密码杂凑算法应用指南](./docs/sm3.md) * [SM4分组密码算法应用指南](./docs/sm4.md) * [SM9标识密码算法应用指南](./docs/sm9.md) +* [CFCA互操作性指南](./docs/cfca.md) ## 包结构 * **SM2** - SM2椭圆曲线公钥密码算法,曲线的具体实现位于[internal/sm2ec](https://github.com/emmansun/gmsm/tree/main/internal/sm2ec) package中。SM2曲线实现性能和Golang SDK中的NIST P256椭圆曲线原生实现(非BoringCrypto)类似,也对**amd64** 和 **arm64**架构做了专门汇编优化实现,您也可以参考[SM2实现细节](https://github.com/emmansun/gmsm/wiki/SM2%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96)及相关Wiki和代码,以获得更多实现细节。SM2包实现了SM2椭圆曲线公钥密码算法的数字签名算法、公钥加密算法、密钥交换算法,以及《GB/T 35276-2017信息安全技术 SM2密码算法使用规范》中的密钥对保护数据格式。 diff --git a/docs/cfca.md b/docs/cfca.md new file mode 100644 index 00000000..721a4c70 --- /dev/null +++ b/docs/cfca.md @@ -0,0 +1,72 @@ +# CFCA互操作性指南 +这是一份**不完整**的CFCA互操作性指南。 + +## 什么是CFCA +CFCA是中国金融认证中心的英文缩写。 + +## 什么是SADK +SADK(Security Application Development Kit)是CFCA推出的一套支持全平台、全浏览器、多语言的安全应用开发套件。实现了证书下载、证书应用过程中的全业务功能覆盖,可与客户业务系统、CFCA RA、CA、统一下载平台无缝对接,为用户提供证书下载、证书更新、签名验签、加密解密等全方位的数字证书安全服务。具体说明请参考[数字证书安全应用开发套件SADK](https://www.cfca.com.cn/20150807/101228565.html)。 + +其JAVA版本(其它语言版本未知)基本上是一个基于[Bouncy Castle](https://www.bouncycastle.org/)的实现(当然它看起来也支持JNI接入OpenSSL、U盾?)。 + +## 为什么会有互操作性问题 +* SADK存在较早,可能有些实现早于标准发布。 +* SADK版本较多,不同版本也会有互操作性兼容问题。 +* 其它未知原因。 + +因为我也找不到SADK的版本历史或者Change Log,这里只是根据有限资料的一些判断。 + +## 容易出现互操作性问题的功能 +相对而言,互操作性问题主要出现在SM2椭圆曲线公钥密码算法应用上,特别是加解密、数字信封加解密上。 + +### SM2加解密 +加解密算法实现部分没有什么互操作性问题,主要是密文格式问题。 + +#### SADK 3.2之前版本 +由于没有版本历史,所以这里只是大致推测(如果有不准确之处,敬请指出)。 +SADK 3.2之前的版本,只支持C1C2C3密文格式,而且C1只支持非压缩点格式,且输出忽略0x04这个点非压缩标识。所以如果和SADK 3.2之前的应用交互,加密输出格式只能选C1C2C3,且密文通过切片操作忽略首字节(0x04这个点非压缩标识);反之,如果是解密SADK 3.2之前的应用提供的密文,则要指定C1C2C3格式,同时,自己在密文前添加0x04这个点非压缩标识。**互操作的重要前提是知道对方的密文格式**。 + +#### SADK 3.2+版本 +SADK 3.2之后的版本,支持下列SM2密文格式(encryptedType): +* 0 - ASN.1编码格式 ```EncryptUtil.encrypt``` 方法默认 +* 2 - C1C3C2 格式,带0x04这个点非压缩标识 +* 4 - C1C3C2 格式,不带0x04这个点非压缩标识 (```EncryptUtil.encryptMessageBySM2 / EncryptUtil.encryptFileBySM2``` 方法默认) +* 8 - C1C2C3 格式,带0x04这个点非压缩标识 +* 16 - C1C2C3 格式,不带0x04这个点非压缩标识 + +SADK 3.2之后的版本,解密过程: +* 先尝试是否ASN.1格式,如果是,就解密;否则, +* 当**C1C3C2,不带0x04这个点非压缩标识**的格式处理,如果解密成功,则结束;否则, +* 当**C1C2C3,不带0x04这个点非压缩标识**的格式处理。 + +从这个解密流程来看,SADK 3.2+可以解密 SADK 3.2之前的SM2密文,反之不行。 + +所以如果和SADK 3.2之后的应用交互,加密输出格式可以是ASN.1编码格式,或者是不带0x04这个点非压缩标识的C1C3C2/C1C2C3格式;反之,如果是解密使用SADK 3.2+的应用提供的密文,则要先区分是否是ASN.1格式,是的话就比较简单;不是的话则要指定C1C3C2格式,同时,自己在密文前添加0x04这个点非压缩标识。**互操作的重要前提是知道对方的密文格式**。 + +### SM2数字信封加解密 +互操作性问题主要出在: +* 数据对称加密所用密钥的SM2密文格式。 +* 对称加密算法的OID。 + +#### SADK 3.2之前版本 +* 数据对称加密密钥的密文格式为**C1C2C3 格式,不带0x04这个点非压缩标识**。这个不符合《GM/T 0010-2010 SM2密码算法加密签名消息语法规范》以及《GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》。 +* SM4-CBC的OID,使用了["SM4" block cipher](https://oid-rep.orange-labs.fr/get/1.2.156.10197.1.104),而不是["SMS4-CBC"](https://oid-rep.orange-labs.fr/get/1.2.156.10197.1.104.2)。 + +本软件库的```pkcs7.EncryptCFCA```方法```DecryptCFCA```方法提供了SADK 3.2之前版本的信封加解密兼容性,记得cipher参数选择```pkcs.SM4```。 + +#### SADK 3.2+版本 +* 数据对称加密密钥的密文格式为**ASN.1编码格式**,这个符合《GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》。 +* SM4-CBC的OID,使用了["SM4" block cipher](https://oid-rep.orange-labs.fr/get/1.2.156.10197.1.104),而不是["SMS4-CBC"](https://oid-rep.orange-labs.fr/get/1.2.156.10197.1.104.2)。 + +本软件库的```pkcs7.EncryptSM```方法```Decrypt```方法提供了SADK 3.2+版本的信封加解密兼容性,记得cipher参数选择```pkcs.SM4```。 + +从SADK 的向下兼容性来看,SADK 3.2+能够解密SADK 3.2之前版本的数字信封加密数据,反之不行。 + +### 解密时自动检测? +要穷举、尝试所有可能的密文格式不是不可以,但这会或多或少地影响解密的性能。你要和对方集成,还是知己知彼比较好,对于加解密来说,对用户透明不代表是好事。本软件库的SM2解密也实现了一定的自动检测(通过首字节判断,基于首字节只有固定那几个的假设): +* 0x30 - ASN.1格式。 +* 0x04 - C1为非压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。 +* 0x02/0x03 - C1为压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。 + +### SM2私钥、证书的解析 +这个是CFCA自定义的,未见相关标准,可以通过```cfca.ParseSM2```来解析。 diff --git a/pkcs7/encrypt.go b/pkcs7/encrypt.go index 96da3a77..bc3acd41 100644 --- a/pkcs7/encrypt.go +++ b/pkcs7/encrypt.go @@ -70,7 +70,7 @@ func Encrypt(cipher pkcs.Cipher, content []byte, recipients []*smx509.Certificat // EncryptSM creates and returns an envelope data PKCS7 structure with encrypted // recipient keys for each recipient public key. -// The OIDs use GM/T 0010 - 2012 set +// The OIDs use GM/T 0010 - 2012 set and the encrypted key use ASN.1 format. // // The algorithm used to perform encryption is determined by the argument cipher func EncryptSM(cipher pkcs.Cipher, content []byte, recipients []*smx509.Certificate) ([]byte, error) {