gmsm/docs/cfca.md
2024-11-18 17:23:59 +08:00

91 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CFCA互操作性指南
这是一份**不完整**的CFCA互操作性指南。
## 什么是CFCA
CFCA是中国金融认证中心的英文缩写。
## 什么是SADK
SADKSecurity 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这个点非压缩标识。
| 随机点 | 密文 | SM3哈希值 |
| :--- | :--- | :--- |
| C1 (64 bytes) | C2 | C3 (32 bytes) |
所以如果和SADK 3.2之前的应用交互加密输出格式只能选C1C2C3且密文通过切片操作忽略首字节0x04这个点非压缩标识反之如果是解密SADK 3.2之前的应用提供的密文则要指定C1C2C3格式同时自己在密文前添加0x04这个点非压缩标识。**互操作的重要前提是知道对方的密文格式**。
#### SADK 3.2+版本
SADK 3.2之后的版本支持下列SM2密文格式(encryptedType)
| encryptedType | 输出格式 | 用本软件库如何解密 |
| :--- | :--- | :--- |
| 0 | ASN.1编码格式 ```EncryptUtil.encrypt``` 方法默认 | 正常解密 |
| 2 | C1C3C2 格式带0x04这个点非压缩标识 | 正常解密 |
| 4 | C1C3C2 格式不带0x04这个点非压缩标识 ```EncryptUtil.encryptMessageBySM2 / EncryptUtil.encryptFileBySM2``` 方法默认) | 添加0x04前缀后解密 |
| 8 | C1C2C3 格式带0x04这个点非压缩标识 | 指定解密Opts后解密 |
| 16 | C1C2C3 格式不带0x04这个点非压缩标识 | 添加0x04前缀同时指定解密Opts后解密 |
**SADK 3.2之后的版本,解密过程**
1. 先尝试是否ASN.1格式,如果是,就解密;否则,
2. 当**C1C3C2不带0x04这个点非压缩标识**的格式处理,如果解密成功,则结束;否则,
3. 当**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数字信封加解密
互操作性问题主要出在:
1. 数据对称加密所用密钥的SM2密文格式。
2. 对称加密算法的OID。```public static final ASN1ObjectIdentifier id_sm4_CBC = new ASN1ObjectIdentifier("1.2.156.10197.1.104");```。
3. 如果需要用本软件库去解密CFCA生成的SM2数字信封目前会有问题。CFCA实现不符合《GB/T 35275-2017信息安全技术 SM2密码算法加密签名消息语法规范》它的**RecipientInfo**默认使用SubjectKeyIdentifier而不是IssuerAndSerialNumber。在SADK 3.7.1.0中需要指定recipientPolicyType=20从证书扩展中获取SubjectKeyID找不到抛异常1根据公钥数据直接计算SubjectKeyID2使用证书的IssuerAndSerialNumber才会使用IssuerAndSerialNumber。正常情况下只有CA证书才一定会在证书扩展中有SubjectKeyID信息。
#### SADK 3.2之前版本
1. 数据对称加密密钥的密文格式为**C1C2C3 格式不带0x04这个点非压缩标识**。这个不符合《GM/T 0010-2012 SM2密码算法加密签名消息语法规范》以及《GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》。
2. 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+版本
1. 数据对称加密密钥的密文格式为**ASN.1编码格式**这个符合《GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》。
2. 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 PKCS7签名数据
```cfca.sadk.util.p7SignMessageAttach / cfca.sadk.util.p7SignMessageDetach```,对应```pkcs7.SignWithoutAttr```如果要Detach签名调用```Finish```之前调用```Detach```就行。
```cfca.sadk.util.p7SignFileAttach / cfca.sadk.util.p7SignFileDetach```类似,只是本软件库不提供对应方法,您可以通过```pkcs7.SignWithoutAttr```自己实现。
参考[cfca sadk 3.0.2.0](https://github.com/emmansun/gmsm/issues/260)
### 解密时自动检测?
要穷举、尝试所有可能的密文格式不是不可以但这会或多或少地影响解密的性能。你要和对方集成还是知己知彼比较好对于加解密来说对用户透明不代表是好事。本软件库的SM2解密也实现了一定的自动检测通过首字节判断基于首字节只有固定那几个的假设
* 0x30 - ASN.1格式。
* 0x04 - C1为非压缩点格式具体是C1C3C2还是C1C2C3取决于解密时的选项参数默认为C1C3C2。
* 0x02/0x03 - C1为压缩点格式具体是C1C3C2还是C1C2C3取决于解密时的选项参数默认为C1C3C2。
### SM2私钥、证书的解析
这个是CFCA自定义的未见相关标准可以通过```cfca.ParseSM2```来解析。