mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 04:36:19 +08:00
pkcs7: code review and refactor
This commit is contained in:
parent
d199697b20
commit
805fa40c97
@ -320,9 +320,9 @@ func calculateSM2Hash(pub *ecdsa.PublicKey, data, uid []byte) ([]byte, error) {
|
|||||||
第一个返回公钥的方法是必须要实现的,后面的方法取决于这个KEY的用途。
|
第一个返回公钥的方法是必须要实现的,后面的方法取决于这个KEY的用途。
|
||||||
|
|
||||||
**注意**:
|
**注意**:
|
||||||
`Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)`方法通常用于对哈希值作签名,最好遵从以下实现逻辑:检查`opts`是否是`*sm2.SM2SignerOption`类型,如果是,则把传入的`digest`作为原始数据进行处理,具体实现可以参考`sm2.SignASN1`函数。当然,目前不管三七二十一,简单当作原始数据大多数情况下都没有问题。实现者可以根据实际应用情况酌情处理。
|
1. `Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)`方法通常用于对哈希值作签名,最好遵从以下实现逻辑:检查`opts`是否是`*sm2.SM2SignerOption`类型,如果是,则把传入的`digest`作为原始数据进行处理,具体实现可以参考`sm2.SignASN1`函数。当然,目前不管三七二十一,简单当作原始数据大多数情况下都没有问题。实现者可以根据实际应用情况酌情处理。
|
||||||
|
2. 如果密码硬件有自己的随机数源,可以忽略传入的`rand`。
|
||||||
如果密码硬件有自己的随机数源,可以忽略传入的`rand`。
|
3. 很多设备签名函数通常只接收哈希值,需要调用```sm2.CalculateSM2Hash```自行计算哈希值。
|
||||||
|
|
||||||
## SM2扩展应用
|
## SM2扩展应用
|
||||||
SM2的一些扩展应用,譬如从签名中恢复公钥、半同态加密、环签名等,大多尚处于POC状态,也无相关标准。其它扩展应用(但凡椭圆曲线公钥密码算法能用到的场合),包括但不限于:
|
SM2的一些扩展应用,譬如从签名中恢复公钥、半同态加密、环签名等,大多尚处于POC状态,也无相关标准。其它扩展应用(但凡椭圆曲线公钥密码算法能用到的场合),包括但不限于:
|
||||||
|
@ -3,6 +3,7 @@ package pkcs7
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto"
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
@ -390,10 +391,16 @@ func signData(data []byte, pkey crypto.PrivateKey, hasher crypto.Hash) ([]byte,
|
|||||||
var opts crypto.SignerOpts = hasher
|
var opts crypto.SignerOpts = hasher
|
||||||
|
|
||||||
if !hasher.Available() {
|
if !hasher.Available() {
|
||||||
// if you pass a private key with type *ecdsa.PrivateKey and the curve is SM2,
|
|
||||||
// you will get unexpected signature.
|
|
||||||
if sm2.IsSM2PublicKey(key.Public()) {
|
if sm2.IsSM2PublicKey(key.Public()) {
|
||||||
opts = sm2.DefaultSM2SignerOpts
|
opts = sm2.DefaultSM2SignerOpts
|
||||||
|
switch realKey := key.(type) {
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
{
|
||||||
|
sm2Key := new(sm2.PrivateKey)
|
||||||
|
sm2Key.PrivateKey = *realKey
|
||||||
|
key = sm2Key
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("pkcs7: unsupported hash function %s", hasher)
|
return nil, fmt.Errorf("pkcs7: unsupported hash function %s", hasher)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/pkcs"
|
"github.com/emmansun/gmsm/pkcs"
|
||||||
"github.com/emmansun/gmsm/sm2"
|
|
||||||
"github.com/emmansun/gmsm/smx509"
|
"github.com/emmansun/gmsm/smx509"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -235,24 +234,7 @@ func (saed *SignedAndEnvelopedData) AddSignerChain(ee *smx509.Certificate, pkey
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key, ok := pkey.(crypto.Signer)
|
signature, err := signData(saed.data, pkey, hasher)
|
||||||
if !ok {
|
|
||||||
return errors.New("pkcs7: private key does not implement crypto.Signer")
|
|
||||||
}
|
|
||||||
|
|
||||||
var signOpt crypto.SignerOpts
|
|
||||||
var tobeSigned []byte
|
|
||||||
|
|
||||||
if _, isSM2 := pkey.(sm2.Signer); isSM2 {
|
|
||||||
signOpt = sm2.DefaultSM2SignerOpts
|
|
||||||
tobeSigned = saed.data
|
|
||||||
} else {
|
|
||||||
signOpt = hasher
|
|
||||||
h := newHash(hasher, saed.digestOid)
|
|
||||||
h.Write(saed.data)
|
|
||||||
tobeSigned = h.Sum(nil)
|
|
||||||
}
|
|
||||||
signature, err := key.Sign(rand.Reader, tobeSigned, signOpt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package pkcs7
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -177,40 +178,47 @@ func TestCreateSignedEvnvelopedDataSM(t *testing.T) {
|
|||||||
}
|
}
|
||||||
sm2Key.D.FillBytes(privKey)
|
sm2Key.D.FillBytes(privKey)
|
||||||
|
|
||||||
|
rootSM2Priv, ok := (*rootCert.PrivateKey).(*sm2.PrivateKey)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("should be sm2 private key")
|
||||||
|
}
|
||||||
|
signKeys := []crypto.PrivateKey{rootSM2Priv, &rootSM2Priv.PrivateKey}
|
||||||
testCipers := []pkcs.Cipher{pkcs.SM4ECB, pkcs.SM4CBC, pkcs.SM4GCM}
|
testCipers := []pkcs.Cipher{pkcs.SM4ECB, pkcs.SM4CBC, pkcs.SM4GCM}
|
||||||
for _, cipher := range testCipers {
|
for _, key := range signKeys {
|
||||||
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
|
for _, cipher := range testCipers {
|
||||||
if err != nil {
|
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
|
||||||
t.Fatal(err)
|
if err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
err = saed.AddSigner(rootCert.Certificate, *rootCert.PrivateKey)
|
}
|
||||||
if err != nil {
|
err = saed.AddSigner(rootCert.Certificate, key)
|
||||||
t.Fatal(err)
|
if err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
err = saed.AddRecipient(recipient.Certificate)
|
}
|
||||||
if err != nil {
|
err = saed.AddRecipient(recipient.Certificate)
|
||||||
t.Fatal(err)
|
if err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
result, err := saed.Finish()
|
}
|
||||||
if err != nil {
|
result, err := saed.Finish()
|
||||||
t.Fatal(err)
|
if err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// fmt.Printf("%x\n", result)
|
// fmt.Printf("%x\n", result)
|
||||||
|
|
||||||
// parse, decrypt, verify
|
// parse, decrypt, verify
|
||||||
p7Data, err := Parse(result)
|
p7Data, err := Parse(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
encKeyBytes, err := p7Data.DecryptAndVerify(recipient.Certificate, *recipient.PrivateKey, func() error {
|
encKeyBytes, err := p7Data.DecryptAndVerify(recipient.Certificate, *recipient.PrivateKey, func() error {
|
||||||
return p7Data.Verify()
|
return p7Data.Verify()
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(encKeyBytes, privKey) {
|
if !bytes.Equal(encKeyBytes, privKey) {
|
||||||
t.Fatal("not same private key")
|
t.Fatal("not same private key")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,7 +291,7 @@ func TestCreateSignedEvnvelopedData(t *testing.T) {
|
|||||||
if recipients[0].SerialNumber.Cmp(recipient.Certificate.SerialNumber) != 0 {
|
if recipients[0].SerialNumber.Cmp(recipient.Certificate.SerialNumber) != 0 {
|
||||||
t.Errorf("Recipient serial number does not match.\n\tExpected:%s\n\tActual:%s", recipient.Certificate.SerialNumber, recipients[0].SerialNumber)
|
t.Errorf("Recipient serial number does not match.\n\tExpected:%s\n\tActual:%s", recipient.Certificate.SerialNumber, recipients[0].SerialNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(recipients[0].RawIssuer, recipient.Certificate.RawIssuer) {
|
if !bytes.Equal(recipients[0].RawIssuer, recipient.Certificate.RawIssuer) {
|
||||||
t.Errorf("Recipient issuer name does not match.\n\tExpected:%x\n\tActual:%x", recipient.Certificate.RawIssuer, recipients[0].RawIssuer)
|
t.Errorf("Recipient issuer name does not match.\n\tExpected:%x\n\tActual:%x", recipient.Certificate.RawIssuer, recipients[0].RawIssuer)
|
||||||
}
|
}
|
||||||
|
@ -214,6 +214,7 @@ var defaultUID = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x
|
|||||||
// Compliance with GB/T 32918.2-2016 5.5.
|
// Compliance with GB/T 32918.2-2016 5.5.
|
||||||
//
|
//
|
||||||
// This function will not use default UID even the uid argument is empty.
|
// This function will not use default UID even the uid argument is empty.
|
||||||
|
// Reference: GM/T 0009-2023 Chapter 8.1.
|
||||||
func CalculateZA(pub *ecdsa.PublicKey, uid []byte) ([]byte, error) {
|
func CalculateZA(pub *ecdsa.PublicKey, uid []byte) ([]byte, error) {
|
||||||
uidLen := len(uid)
|
uidLen := len(uid)
|
||||||
if uidLen > 0x1fff {
|
if uidLen > 0x1fff {
|
||||||
@ -263,6 +264,7 @@ func bigIntToBytes(curve elliptic.Curve, value *big.Int) []byte {
|
|||||||
// If the UID is not provided, a default UID (1234567812345678) is used.
|
// If the UID is not provided, a default UID (1234567812345678) is used.
|
||||||
// The public key must be valid, otherwise will be panic.
|
// The public key must be valid, otherwise will be panic.
|
||||||
// This function is used to calculate the hash value for SM2 signature.
|
// This function is used to calculate the hash value for SM2 signature.
|
||||||
|
// Reference: GM/T 0009-2023 Chapter 8.1 and 8.2.
|
||||||
func CalculateSM2Hash(pub *ecdsa.PublicKey, data, uid []byte) ([]byte, error) {
|
func CalculateSM2Hash(pub *ecdsa.PublicKey, data, uid []byte) ([]byte, error) {
|
||||||
if len(uid) == 0 {
|
if len(uid) == 0 {
|
||||||
uid = defaultUID
|
uid = defaultUID
|
||||||
|
Loading…
x
Reference in New Issue
Block a user