diff --git a/docs/pkcs7.md b/docs/pkcs7.md index d088664..1faef28 100644 --- a/docs/pkcs7.md +++ b/docs/pkcs7.md @@ -40,18 +40,25 @@ ### 签名数据(Signed Data) 签名数据,使用证书对应的私钥进行签名,理论上支持多个签名者,但通常使用场景都是单签。和数字信封数据类似,也分国密和非国密。 -#### 创建签名数据 +#### 签名流程 +1. 创建SignedData (是否国密是指OID也使用国密体系) -| 是否国密 | 方法 | 默认签名算法 | -| :--- | :--- | :--- | -| 否 | ```NewSignedData``` | SHA1 | -| 是 | ```NewSMSignedData``` | SM3 | +| 是否国密 | 数据是否是哈希值 | 方法 | 默认签名算法 | +| :--- | :--- | :--- | :--- | +| 否 | 否 | ```NewSignedData``` | SHA1 | +| 否 | 是 | ```NewSignedDataWithDigest``` | SHA1 | +| 是 | 否 | ```NewSMSignedData``` | SM3 | +| 是 | 是 | ```NewSMSignedDataWithDigest``` | SM3 | -可选步骤:调用```SetDigestAlgorithm```设置想要的签名算法,通常国密不需要修改。 -接着调用```AddSigner```或```AddSignerChain```方法,进行签名;可以通过```SignerInfoConfig.SkipCertificates```指定忽略证书项(最终签名数据中不包含证书项); -如果进行Detach签名,则调用```Detach```方法; -最后调用```Finish```方法,序列化输出结果。 +2. 可选步骤:调用```SetDigestAlgorithm```设置想要的签名算法,通常国密**不需要**修改。 +3. 接着调用```AddSigner```或```AddSignerChain```方法,进行签名;可以通过```SignerInfoConfig.SkipCertificates```指定忽略证书项(最终签名数据中不包含证书项); +4. 如果进行Detach签名,则调用```Detach```方法; +5. 最后调用```Finish```方法,序列化输出结果。 + +**注意**: +1. 如果是直接对哈希值签名,一定是Detach签名。 +2. 国密签名如果要传入哈希值,在有Attribute的情况下,则哈希值只是标准的SM3哈希值;否则必须是符合SM2签名标准的哈希值(含SM2公钥信息)。 #### Detach签名 就是外部签名,**被签名数据**不包含在SignedData中(也就是其ContentInfo.Content为空)。 @@ -86,7 +93,7 @@ if err := p7.VerifyWithChain(truststore); err != nil { 1. 调用```Parse```方法; 2. 如果是Detach签名数据,则手动设置原始数据(参考```testSign```方法); 3. 如果签名数据中不包含证书项,则手动设置验签证书(参考```TestSkipCertificates```); -4. 调用```Verify```或```VerifyWithChain```方法。 +4. 如果Content是原始数据,调用```Verify```或```VerifyWithChain```方法;如果Content是哈希值,调用```VerifyAsDigest```或```VerifyAsDigestWithChain```方法。 #### 特殊方法 ```DegenerateCertificate```,退化成签名数据中只包含证书,目前没有使用SM2 OID的方法,如果需要可以请求添加。可以参考```TestDegenerateCertificate```和```TestParseSM2CertificateChain```。 diff --git a/pkcs7/sign.go b/pkcs7/sign.go index 388d282..61913a1 100644 --- a/pkcs7/sign.go +++ b/pkcs7/sign.go @@ -48,9 +48,9 @@ func NewSignedData(data []byte) (*SignedData, error) { return &SignedData{sd: sd, data: data, digestOid: OIDDigestAlgorithmSHA1, contentTypeOid: OIDSignedData}, nil } -// NewSignedDataWithDigest creates a new SignedData instance using the provided digest. -// It sets the isDigest field to true, indicating that the input is already a digest. -// Returns the SignedData instance or an error if the creation fails. +// NewSignedDataWithDigest creates a new SignedData structure with the provided digest. +// The digest is used to initialize the SignedData object, and the content is set to an empty ASN.1 RawValue. +// The function returns a pointer to the SignedData object and an error if any occurs. func NewSignedDataWithDigest(digest []byte) (*SignedData, error) { ci := contentInfo{ ContentType: OIDData, @@ -64,9 +64,10 @@ func NewSignedDataWithDigest(digest []byte) (*SignedData, error) { return &SignedData{sd: sd, data: digest, digestOid: OIDDigestAlgorithmSHA1, contentTypeOid: OIDSignedData, isDigestProvided: true}, nil } -// NewSMSignedData takes data and initializes a PKCS7 SignedData struct that is -// ready to be signed via AddSigner. The digest algorithm is set to SM3 by default -// and can be changed by calling SetDigestAlgorithm. +// NewSMSignedData creates a new SignedData object using the provided data +// and sets the appropriate OIDs for SM2 and SM3 algorithms. +// It returns a pointer to the SignedData object and an error if any occurs +// during the creation of the SignedData object. func NewSMSignedData(data []byte) (*SignedData, error) { sd, err := NewSignedData(data) if err != nil { @@ -78,25 +79,28 @@ func NewSMSignedData(data []byte) (*SignedData, error) { return sd, nil } -// NewSMSignedDataWithDigest creates a new SignedData object using the provided digest. -// It calls the NewSMSignedData function with the given digest and sets the isDigest flag to true. -// If there is an error during the creation of the SignedData object, it returns the error. +// NewSMSignedDataWithDigest creates a new SignedData structure with the provided digest. +// The digest is expected to be a precomputed hash of the content to be signed. +// This function initializes the SignedData with the necessary OIDs for SM3 and SM2 algorithms. func NewSMSignedDataWithDigest(digest []byte) (*SignedData, error) { - sd, err := NewSignedDataWithDigest(digest) - if err != nil { - return nil, err + ci := contentInfo{ + ContentType: SM2OIDData, + Content: asn1.RawValue{}, // for sign digest, content is empty } - sd.sd.ContentInfo.ContentType = SM2OIDData - sd.digestOid = OIDDigestAlgorithmSM3 - sd.contentTypeOid = SM2OIDSignedData - return sd, nil + sd := signedData{ + ContentInfo: ci, + Version: 1, + } + return &SignedData{sd: sd, data: digest, digestOid: OIDDigestAlgorithmSM3, contentTypeOid: SM2OIDSignedData, isDigestProvided: true}, nil } -// SignerInfoConfig are optional values to include when adding a signer +// SignerInfoConfig contains configuration options for the signer information. +// It allows specifying additional signed and unsigned attributes, as well as +// an option to skip adding certificates to the payload. type SignerInfoConfig struct { - ExtraSignedAttributes []Attribute - ExtraUnsignedAttributes []Attribute - SkipCertificates bool // Skip adding certificates to the payload + ExtraSignedAttributes []Attribute // Additional attributes to be included in the signed attributes. + ExtraUnsignedAttributes []Attribute // Additional attributes to be included in the unsigned attributes. + SkipCertificates bool // Skip adding certificates to the payload } type signedData struct { diff --git a/pkcs7/verify.go b/pkcs7/verify.go index e629de1..3436a45 100644 --- a/pkcs7/verify.go +++ b/pkcs7/verify.go @@ -170,7 +170,6 @@ func parseSignedData(data []byte) (*PKCS7, error) { if err != nil { return nil, err } - // fmt.Printf("--> Signed Data Version %d\n", sd.Version) var compound asn1.RawValue var content unsignedData