gmsm

CFCA互操作性指南

这是一份不完整的CFCA互操作性指南。

什么是CFCA

CFCA是中国金融认证中心的英文缩写。

什么是SADK

SADK(Security Application Development Kit)是CFCA推出的一套支持全平台、全浏览器、多语言的安全应用开发套件。实现了证书下载、证书应用过程中的全业务功能覆盖,可与客户业务系统、CFCA RA、CA、统一下载平台无缝对接,为用户提供证书下载、证书更新、签名验签、加密解密等全方位的数字证书安全服务。具体说明请参考数字证书安全应用开发套件SADK

其JAVA版本(其它语言版本未知)基本上是一个基于Bouncy Castle的实现(当然它看起来也支持JNI接入OpenSSL、U盾?)。

为什么会有互操作性问题

因为我也找不到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数字信封,目前会有问题(从v0.29.3开始可以解密)。CFCA实现不符合《GB/T 35275-2017:信息安全技术 SM2密码算法加密签名消息语法规范》,它的RecipientInfo默认使用SubjectKeyIdentifier而不是IssuerAndSerialNumber。在SADK 3.7.1.0中,需要指定recipientPolicyType=2(0:从证书扩展中获取SubjectKeyID,找不到抛异常;1:根据公钥数据直接计算SubjectKeyID;2:使用证书的IssuerAndSerialNumber)才会使用IssuerAndSerialNumber。正常情况下,只有CA证书才一定会在证书扩展中有SubjectKeyID信息。如果要产生和CFCA一样的加密信封,请使用pkcs7.EnvelopeMessageCFCA方法。

SADK 3.2之前版本

  1. 数据对称加密密钥的密文格式为C1C2C3 格式,不带0x04这个点非压缩标识。这个不符合《GM/T 0010-2012 SM2密码算法加密签名消息语法规范》以及《GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》。
  2. SM4-CBC的OID,使用了“SM4” block cipher,而不是“SMS4-CBC”

本软件库的pkcs7.EncryptCFCA方法DecryptCFCA方法提供了SADK 3.2之前版本的信封加解密兼容性,记得cipher参数选择pkcs.SM4。但是pkcs7.EncryptCFCA方法产生的加密信封依然使用IssuerAndSerialNumber作为RecipientInfo。

SADK 3.2+版本

  1. 数据对称加密密钥的密文格式为ASN.1编码格式,这个符合《GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》。
  2. SM4-CBC的OID,使用了“SM4” block cipher,而不是“SMS4-CBC”

本软件库的pkcs7.EncryptSM方法Decrypt方法提供了SADK 3.2+版本的信封加解密兼容性,记得cipher参数选择pkcs.SM4pkcs7.EncryptSM方法符合GB/T 35275-2017 信息安全技术 SM2密码算法加密签名消息语法规范》,CFCA的SADK能解密。

本软件库的pkcs7.EnvelopeMessageCFCA方法提供了CFCA SADK更兼容的实现,也就是recipientPolicyType=0。

从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

解密时自动检测?

要穷举、尝试所有可能的密文格式不是不可以,但这会或多或少地影响解密的性能。你要和对方集成,还是知己知彼比较好,对于加解密来说,对用户透明不代表是好事。本软件库的SM2解密也实现了一定的自动检测(通过首字节判断,基于首字节只有固定那几个的假设):

SM2私钥、证书的解析

这个是CFCA自定义的,未见相关标准,可以通过cfca.ParseSM2来解析。