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的用途。
|
||||
|
||||
**注意**:
|
||||
`Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)`方法通常用于对哈希值作签名,最好遵从以下实现逻辑:检查`opts`是否是`*sm2.SM2SignerOption`类型,如果是,则把传入的`digest`作为原始数据进行处理,具体实现可以参考`sm2.SignASN1`函数。当然,目前不管三七二十一,简单当作原始数据大多数情况下都没有问题。实现者可以根据实际应用情况酌情处理。
|
||||
|
||||
如果密码硬件有自己的随机数源,可以忽略传入的`rand`。
|
||||
1. `Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)`方法通常用于对哈希值作签名,最好遵从以下实现逻辑:检查`opts`是否是`*sm2.SM2SignerOption`类型,如果是,则把传入的`digest`作为原始数据进行处理,具体实现可以参考`sm2.SignASN1`函数。当然,目前不管三七二十一,简单当作原始数据大多数情况下都没有问题。实现者可以根据实际应用情况酌情处理。
|
||||
2. 如果密码硬件有自己的随机数源,可以忽略传入的`rand`。
|
||||
3. 很多设备签名函数通常只接收哈希值,需要调用```sm2.CalculateSM2Hash```自行计算哈希值。
|
||||
|
||||
## SM2扩展应用
|
||||
SM2的一些扩展应用,譬如从签名中恢复公钥、半同态加密、环签名等,大多尚处于POC状态,也无相关标准。其它扩展应用(但凡椭圆曲线公钥密码算法能用到的场合),包括但不限于:
|
||||
|
@ -3,6 +3,7 @@ package pkcs7
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
@ -390,10 +391,16 @@ func signData(data []byte, pkey crypto.PrivateKey, hasher crypto.Hash) ([]byte,
|
||||
var opts crypto.SignerOpts = hasher
|
||||
|
||||
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()) {
|
||||
opts = sm2.DefaultSM2SignerOpts
|
||||
switch realKey := key.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
{
|
||||
sm2Key := new(sm2.PrivateKey)
|
||||
sm2Key.PrivateKey = *realKey
|
||||
key = sm2Key
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("pkcs7: unsupported hash function %s", hasher)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/emmansun/gmsm/pkcs"
|
||||
"github.com/emmansun/gmsm/sm2"
|
||||
"github.com/emmansun/gmsm/smx509"
|
||||
)
|
||||
|
||||
@ -235,24 +234,7 @@ func (saed *SignedAndEnvelopedData) AddSignerChain(ee *smx509.Certificate, pkey
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key, ok := pkey.(crypto.Signer)
|
||||
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)
|
||||
signature, err := signData(saed.data, pkey, hasher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package pkcs7
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"encoding/pem"
|
||||
"math/big"
|
||||
@ -177,40 +178,47 @@ func TestCreateSignedEvnvelopedDataSM(t *testing.T) {
|
||||
}
|
||||
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}
|
||||
for _, cipher := range testCipers {
|
||||
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = saed.AddSigner(rootCert.Certificate, *rootCert.PrivateKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = saed.AddRecipient(recipient.Certificate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := saed.Finish()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, key := range signKeys {
|
||||
for _, cipher := range testCipers {
|
||||
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = saed.AddSigner(rootCert.Certificate, key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = saed.AddRecipient(recipient.Certificate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := saed.Finish()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// fmt.Printf("%x\n", result)
|
||||
// fmt.Printf("%x\n", result)
|
||||
|
||||
// parse, decrypt, verify
|
||||
p7Data, err := Parse(result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
encKeyBytes, err := p7Data.DecryptAndVerify(recipient.Certificate, *recipient.PrivateKey, func() error {
|
||||
return p7Data.Verify()
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(encKeyBytes, privKey) {
|
||||
t.Fatal("not same private key")
|
||||
// parse, decrypt, verify
|
||||
p7Data, err := Parse(result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
encKeyBytes, err := p7Data.DecryptAndVerify(recipient.Certificate, *recipient.PrivateKey, func() error {
|
||||
return p7Data.Verify()
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(encKeyBytes, privKey) {
|
||||
t.Fatal("not same private key")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
//
|
||||
// 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) {
|
||||
uidLen := len(uid)
|
||||
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.
|
||||
// The public key must be valid, otherwise will be panic.
|
||||
// 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) {
|
||||
if len(uid) == 0 {
|
||||
uid = defaultUID
|
||||
|
Loading…
x
Reference in New Issue
Block a user