由于最近项目中需要根据国家密码局的规范(GM/T 0010)实现SM2密码算法加密签名消息数据的封装,花了些时间进行了下研究,现属文以记之~(^_−)☆ 接下来先介绍sm2算法的消息语法规范,至于具体如何通过gmssl库去实现消息数据的封装,小编将在之后的文章中逐一讲解。OK, 进入正题~
首先我们知道PKCS#7中规定了6种数据内容:明文数据(Data)、签名数据(Signed-data),数字信封数据(Enveloped-data),带签名的数字信封数据(Signed-and-enveloped-data),摘要数据(Digested-data),加密数据(Encrypted-data)。(有兴趣的还可以看看rfc2315 (https://tools.ietf.org/html/rfc2315) ,全英文文档哦(*^▽^*))
同样国密局参考p7规范,对这6种类型进行了定义(具体见GM/T 0010规范http://www.doc88.com/p-7965091429139.html)。那国密规范中定义的6中数据类型与国际标准中的有什么区别呢? (•ิ_•ิ)?
其实区别不是很大,都是将数据封装到pkcs7结构中(国际标准的消息数据封装通过openssl中的pkcs7模块实现,而国密规范的消息数据封装是通过gmssl中的pkcs7模块实现,GmSSL (http://gmssl.org) 是支持国密算法和标准的OpenSSL分支)。那么接下来我们细细聊一下GM/T 0010规范中的6中类型及与RFC中的区别。
RFC中各类型标识符定义如下:
对象标识符OID | 对象标识符定义 | GmSSL/OpenSSL中NID |
---|---|---|
1.2.840.113549.1.7.1 | 数据类型data | NID_pkcs7_data |
1.2.840.113549.1.7.2 | 签名数据类型signedData | NID_pkcs7_signed |
1.2.840.113549.1.7.3 | 数字信封数据类型envelopedData | NID_pkcs7_enveloped |
1.2.840.113549.1.7.4 | 签名及数字信封数据类型signedAndEnvelopedData | NID_pkcs7_signedAndEnveloped |
1.2.840.113549.1.7.5 | 摘要数据类型digestData | NID_pkcs7_digest |
1.2.840.113549.1.7.6 | 加密数据类型encryptedData | NID_pkcs7_encrypted |
GM/T 0010各类型标识符定义,详见下表:
对象标识符OID | 对象标识符定义 | GmSSL/OpenSSL中NID |
---|---|---|
1.2.156.10197.6.1.4.2 | SM2密码算法加密签名消息语法规范 | 无 |
1.2.156.10197.6.1.4.2.1 | 数据类型data | 无 |
1.2.156.10197.6.1.4.2.2 | 签名数据类型signedData | 无 |
1.2.156.10197.6.1.4.2.3 | 数字信封数据类型envelopedData | 无 |
1.2.156.10197.6.1.4.2.4 | 签名及数据信封数据类型signedAndEnvelopedData | 无 |
1.2.156.10197.6.1.4.2.5 | 加密数据类型encrypedData | 无 |
1.2.156.10197.6.1.4.2.6 | 密钥协商类型keyAgreementInfo | 无
|
相对于RFC规范,GM/T 0010规范中没有摘要数据类型,添加了密钥协商类型。且目前gmssl/openssl库中并不支持GM/T 0010规范中各类型标识符(注,小编用的是gmssl 2.4.2版本)。这也是我们后续编码构造国密消息语法规范的数据时需要解决的问题之一。
Version类型标明语法版本号。
Version ::= INTEGER
ContentEncryptionAlgorithmIdentifier类型标明一个数据加密算法。其OID见GM/T0006标准。
ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
例如,gmssl库中已定义的SM4算法相关OID如下:
NID_sms4_ecb, /* OBJ_sms4_ecb 1 2 156 10197 1 104 1 */
NID_sms4_cbc, /* OBJ_sms4_cbc 1 2 156 10197 1 104 2 */
NID_sms4_ofb128, /* OBJ_sms4_ofb128 1 2 156 10197 1 104 3 */
NID_sms4_cfb128, /* OBJ_sms4_cfb128 1 2 156 10197 1 104 4 */
NID_sms4_cfb1, /* OBJ_sms4_cfb1 1 2 156 10197 1 104 5 */
NID_sms4_cfb8, /* OBJ_sms4_cfb8 1 2 156 10197 1 104 6 */
NID_sms4_ctr, /* OBJ_sms4_ctr 1 2 156 10197 1 104 7 */
NID_sms4_gcm, /* OBJ_sms4_gcm 1 2 156 10197 1 104 8 */
NID_sms4_ccm, /* OBJ_sms4_ccm 1 2 156 10197 1 104 9 */
NID_sms4_xts, /* OBJ_sms4_xts 1 2 156 10197 1 104 10 */
NID_sms4_wrap, /* OBJ_sms4_wrap 1 2 156 10197 1 104 11 */
NID_sms4_wrap_pad, /* OBJ_sms4_wrap_pad 1 2 156 10197 1 104 12 */
NID_sms4_ocb, /* OBJ_sms4_ocb 1 2 156 10197 1 104 100 */
DigestAlgorithmIdentifier类型标识消息摘要算法,在GM/T0010标准中为SM3算法,其OID为:1.2.156.10197.1.401
DigestAlgorithmIdentifier ::= AlgorithmIdentifier
DigestEncryptionAlgorithmIdentifier类型标明一个签名算法,在GM/T0010标准中为SM2-1数字签名算法,其OID为:1.2.156.10197.1.301.1
DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
ExtendedCertificatesAndCertificate类型指定一个PKCS#6扩展证书或者一个X.509证书。这一类型见PKCS#6第6节推荐的语法:
ExtendedCertificateOrCertificate ::= CHOICE {
certificate Certificate, -- X.509
extendedCertificate [0] IMPLICIT ExtendedCertificate
}
IssuerAndSerialNumber类型标明一个证书颁发者可识别名和颁发者的证书序列号,可据此确定一份证书和与此证书对应的实体及公钥。
IssuerAndSerialNumber ::= SEQUENCE {
issuer Name,
serialNumber CertificateSerialNumber
}
ContentInfo类型标明了实体之间交换内容的通用语法结构,定义如下:
ContentInfo ::= SEQUENCE {
contentType ContentType,
content[0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
}
ContentType ::= OBJECT IDENTIFIER
其中:
ContentType 内容类型。它是一个对象标识符,这意味着它是由定义内容类型的权威分配的唯一整数字符串。也就是六种内容类型:data、signedData、envelopedData、signedAndEnvelopedData、digestddata和encryptedData对应的对象标识符。(对于SM2算法的消息语法规范即为GM/T 0010中定义的各类型标识符OID)
content 内容,可选
CertificateRevocationLists类型标明一个证书撤销列表的集合。它的目的是让集合包含足够的信息来确定与该集合相关联的证书是否仍有效。
CertificateRevocationLists ::= SET OF CertificateRevocationList
data数据类型结构定义如下:
Data ::= OCTET STRING
Data数据类型标识任意的字符串,比如ASCII文本文件。也就是说这样的字符串不需要有任何内部结构(当然也可以有),它们甚至可能是DER编码的数据。该类型与rfc2315中定义是一样一样的。
signedData数据类型有任意类型的数和至少一个签名者的签名值组成。任意类型的数据能够同时被任意数量的签名者签名。signedData数据类型结构定义如下:
SignedData ::= SEQUENCE {
version Version,
digestAlgorithms DigestAlgorithmIdentifiers,
contentInfo ContentInfo,
certificates[0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
crls[1] IMPLICIT CertificateRevocationLists OPTIONAL,
signerInfos SignerInfos
}
DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
SignerInfos ::= SET OF SignerInfo
结构中各项含义见下表
字段名称 | 数据类型 | 解释 | 备注 |
---|---|---|---|
version | Version | 语法的版本号 | RFC2315 v1.5规范中这一版本号为1 |
digestAlgorithms | DigestAlgorithmIdentifiers | 消息摘要算法标识符的集合 | 可以包含任意数量的元素,包括0。每一个元素标识一种消息摘要算法(和任何相应的参数) |
contentInfo | ContentInfo | 被签名的数据内容,数据类型见GM/T 0009 | 在GM/T 0010规范中该字段类型写的是SM2Signature,但根据GM/T 0009规范中的定义,SM2Signature是签名结果的数据类型,与该字段含义所说的被签名的数据内容不符,且签名值在signerInfos中会有记录。(小编大胆猜测是规范撰写人员粗心写错了(ー△ー;),应该为ContentInfo类型,即签名原文数据) |
certificates | ExtendedCertificatesAndCertificates | PKCS#6扩展证书和X.509证书的集合 | 对于签名数据,这里可以存储签名者的证书 |
crls | CertificateRevocationLists | 证书撤销列表的集合 | 撤销列表可以用来决定certificates域中的证书是否是“hot listed”的,但这不是必须的。 |
signerInfos | SignerInfo集合 | 每个签名者信息的集合 |
国密规范定义的签名者信息结构定义与RFC中一致。只是某些字段的含义存在歧义(注意红色标注部分)
SignerInfo结构定义如下:
SignerInfo ::= SEQUENCE {
version Version,
issuerAndSerialNumber IssuerAndSerialNumber,
digestAlgorithm DigestAlgorithmIdentifier,
authenticatedAttributes[0] IMPLICIT Attributes OPTIONAL,
digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
encryptedDigest EncryptedDigest,
unauthenticatedAttributes[1] IMPLICIT Attributes OPTIONAL
}
EncryptedDigest ::= OCTET STRING
结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
version | Version | 语法的版本号。(RFC2315 v1.5规范中这一版本号为1) |
issuerAndSerialNumber | IssuerAndSerialNumber | 一个证书颁发者可识别名和颁发者确定的证书序列号,可据此确定一份证书和与此证书对应的实体及公钥。 |
digestAlgorithm | DigestAlgorithmIdentifier | 对内容进行摘要计算的消息摘要算法,GM/T 0010规范采用SM3算法 |
authenticatedAttributes[0] | Attributes | 是经由签名者签名的属性的集合,该域是可选的。如果该域存在,该域中摘要的就是方法是对原文进行摘要计算结果 |
digestEncryptionAlgorithm | DigestEncryptionAlgorithmIdentifier | SM2-1椭圆曲线数字签名算法标识符 |
encryptedDigest | OCTET STRING | 签名结果。注,GM/T0010规范中说明这里值是SM2Signature。编码格式为r||s.根据pkcs#7理解,填入的数据应为SM2Signature签名值结构数据经过DER编码后的数据 |
unauthenticatedAttributes | Attributes | 不被签名的属性的集合 |
国密规范定义的签名者信息结构定义与RFC中一致。只是某些字段的含义有些区别(注意红色标注部分)
数字信封envelopedData数据类型有加密数据和至少一个接收者的数据加密密钥的密文组成。其中加密数据是用数据加密密钥加密的,数据加密密钥是有接收者的公钥加密的。
该类型用于为接收者的data、digestData或signedData三种类型的数据做数字信封。
envelopedData数据类型结构定义如下:
EnvelopedData ::= SEQUENCE {
version Version,
recipientInfos RecipientInfos,
encryptedContentInfo EncryptedContentInfo
}
RecipientInfos ::= SET OF RecipientInfo
EncryptedContentInfo ::= SEQUENCE {
contentType ContentType,
contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
encryptedContent[0] IMPLICIT EncryptedContent OPTIONAL,
sharedInfo[1] IMPLICIT OCTET STRING OPTIONAL,
sharedInfo[2] IMPLICIT OCTET STRING OPTIONAL
}
EncryptedContent ::= OCTET STRING
envelopedData结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
version | Version | 语法的版本号,(RFC2315 v1.5规范中这一版本号为0) |
recipientInfos | RecipientInfos | 每个接收者信息的集合,至少要有一个接收者。 |
encryptedContentInfo | EncryptedContentInfo | 已加密的内容信息 |
encryptedContentInfo结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
contentType | ContentType | 内容的类型 |
contentEncryptionAlgorithm | ContentEncryptionAlgorithm | 内容加密算法(和相关的参数) |
encryptedContent | EncryptedContent | 内容加密结果,可选。如果该字段不存在,则必须通过其他方式提供其预期值。填入数据为国密规范定义的密文保护结构经过DER编码后的数据 |
sharedInfo | OCTET STRING | 协商好的共享信息,可选 |
sharedInfo | OCTET STRING | 协商好的共享信息,可选 |
国密规范中定义的数字信封结构相较于RFC规范中,新增了2个字段用于存放协商好的共享信息。
每个接收者信息用RecipientInfo类型表示,其类型结构定义如下:
RecipientInfo ::= SEQUENCE {
version Version,
issuerAndSerialNumber IssuerAndSerialNumber,
keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
encryptedKey EncryptedKey
}
EncryptedKey ::= OCTET STRING
结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
version | Version | 语法的版本号。(RFC2315 v1.5规范中这一版本号为0) |
issuerAndSerialNumber | IssuerAndSerialNumber | 一个证书颁发者可识别名和颁发者确定的证书序列号,可据此确定一份证书和与此证书对应的实体及公钥 |
keyEncryptionAlgorithm | KeyEncryptionAlgorithmIdentifier | 用接收者公钥加密数据加密密钥的算法,为SM2-3椭圆曲线加密算法 |
encryptedKey | EncryptedKey | 数据加密密钥密文SM2Cipher,其定义见GM/T 0009。填入数据应为SM2Cipher结构经过DER编码后的数据 |
接收者信息类型结构定义与RFC中差不多。只是某些字段的含义有些区别(注意红色标注部分)
signedAndEnvelopedData数据类型有任意类型的加密数据、至少一个接收者的数据加密密钥和至少一个签名者的签名组成。其结构定义如下:
SignedAndEnvelopedData ::= SEQUENCE {
version Version,
recipientInfos RecipientInfos,
digestAlgorithms DigestAlgorithmIdentifiers,
encryptedContentInfo EncryptedContentInfo,
certificates[0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
crls[1] IMPLICIT CertificateRevocationLists OPTIONAL,
signerInfos SignerInfos
}
结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
version | Version | 语法的版本号。(RFC2315 v1.5规范中这一版本号为1) |
recipientInfos | RecipientInfos | 每个接收者信息的集合,至少一个元素 |
digestAlgorithms | DigestAlgorithmIdentifiers | 消息摘要算法标识符的集合 |
encryptedContentInfo | EncryptedContentInfo | 已加密的内容,可以是任何定义的数据类型 |
certificates | ExtendedCertificatesAndCertificates | PKCS#6扩展证书或者一个X.509证书的集合,是可选的 |
crls | CertificateRevocationLists | 证书撤销列表的集合 |
signerInfos | SignerInfos | 每个签名者的集合,至少要有一个元素 |
国密规范定义的签名及数字信封类型结构与RFC中一样。
encryptedData数据类型有任意类型的已加密的数据组成,数据类型既没有接收者也没有加密的数据加密密钥。其结构定义如下:
EncryptedData ::= SEQUENCE {
version Version,
encryptedContentInfo EncryptedContentInfo
}
结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
version | Version | 语法的版本号。(RFC2315 v1.5规范中这一版本号为0) |
encryptedContentInfo | EncryptedContentInfo | 已加密的内容信息 |
国密规范中该类型结构与RFC中一致。
密钥协商数据类型标明两个用户之间建立一个共享秘密密钥的结构,通过这种方式能够确定一个共享秘密密钥的值。
该类型用于两个用户为产生共享秘密密钥进行的公共参数交换。
KeyAgreementInfo ::= SEQUENCE {
version Version(1),
tempPublicKeyR SM2PublicKey,
userCertificate Certificate,
userID OCTET STRING
}
结构中各项含义见下表
字段名称 | 数据类型 | 含义 |
---|---|---|
version | Version | 语法的版本号。 |
tempPublicKeyR | SM2PublicKey | 临时公钥,结构定义见GM/T 0006 |
userCertificate | Certificate | 用户证书 |
userID | OCTET STRING | 用户标识 |
OK,GM/T 0010规范解析介绍到这,之后的文章中将聊聊如何构造SM2算法的消息数据。。。。。。。。。。 (((┏(; ̄▽ ̄)┛装完逼就跑