mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 12:16:20 +08:00
pkcs7: remove deprecated method SignWithSM2
This commit is contained in:
parent
6b18205bba
commit
d199697b20
18
docs/sm2.md
18
docs/sm2.md
@ -306,6 +306,24 @@ func calculateSM2Hash(pub *ecdsa.PublicKey, data, uid []byte) ([]byte, error) {
|
|||||||
```
|
```
|
||||||
公钥加密就没啥特殊,只要确保输出密文的编码格式和KMS一致即可。
|
公钥加密就没啥特殊,只要确保输出密文的编码格式和KMS一致即可。
|
||||||
|
|
||||||
|
## 基于密码硬件,定制SM2私钥
|
||||||
|
密码硬件(SDF/SKF)中的私钥通常是无法导出的,但通常提供了签名、解密APIs供调用,为了和本软件库集成,通常需要自定义实现以下接口:
|
||||||
|
|
||||||
|
1. `crypto.Signer`,这个接口的实现通常把传入的数据作为哈希值。
|
||||||
|
2. `crypto.Decrypter`,这个接口用于解密操作。
|
||||||
|
|
||||||
|
通常需要实现四个方法:
|
||||||
|
1. `Public() crypto.PublicKey`
|
||||||
|
2. `Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)`
|
||||||
|
3. `Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error)`
|
||||||
|
|
||||||
|
第一个返回公钥的方法是必须要实现的,后面的方法取决于这个KEY的用途。
|
||||||
|
|
||||||
|
**注意**:
|
||||||
|
`Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)`方法通常用于对哈希值作签名,最好遵从以下实现逻辑:检查`opts`是否是`*sm2.SM2SignerOption`类型,如果是,则把传入的`digest`作为原始数据进行处理,具体实现可以参考`sm2.SignASN1`函数。当然,目前不管三七二十一,简单当作原始数据大多数情况下都没有问题。实现者可以根据实际应用情况酌情处理。
|
||||||
|
|
||||||
|
如果密码硬件有自己的随机数源,可以忽略传入的`rand`。
|
||||||
|
|
||||||
## SM2扩展应用
|
## SM2扩展应用
|
||||||
SM2的一些扩展应用,譬如从签名中恢复公钥、半同态加密、环签名等,大多尚处于POC状态,也无相关标准。其它扩展应用(但凡椭圆曲线公钥密码算法能用到的场合),包括但不限于:
|
SM2的一些扩展应用,譬如从签名中恢复公钥、半同态加密、环签名等,大多尚处于POC状态,也无相关标准。其它扩展应用(但凡椭圆曲线公钥密码算法能用到的场合),包括但不限于:
|
||||||
* [确定性签名](https://datatracker.ietf.org/doc/html/rfc6979)
|
* [确定性签名](https://datatracker.ietf.org/doc/html/rfc6979)
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
type SignedData struct {
|
type SignedData struct {
|
||||||
sd signedData
|
sd signedData
|
||||||
certs []*smx509.Certificate
|
certs []*smx509.Certificate
|
||||||
data, messageDigest []byte
|
data []byte
|
||||||
contentTypeOid asn1.ObjectIdentifier
|
contentTypeOid asn1.ObjectIdentifier
|
||||||
digestOid asn1.ObjectIdentifier
|
digestOid asn1.ObjectIdentifier
|
||||||
encryptionOid asn1.ObjectIdentifier
|
encryptionOid asn1.ObjectIdentifier
|
||||||
@ -167,30 +167,11 @@ func (sd *SignedData) AddSignerChain(ee *smx509.Certificate, pkey crypto.Private
|
|||||||
sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers,
|
sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers,
|
||||||
pkix.AlgorithmIdentifier{Algorithm: sd.digestOid, Parameters: asn1.NullRawValue},
|
pkix.AlgorithmIdentifier{Algorithm: sd.digestOid, Parameters: asn1.NullRawValue},
|
||||||
)
|
)
|
||||||
hasher, err := getHashForOID(sd.digestOid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h := newHash(hasher, sd.digestOid)
|
|
||||||
h.Write(sd.data)
|
|
||||||
sd.messageDigest = h.Sum(nil)
|
|
||||||
encryptionOid, err := getOIDForEncryptionAlgorithm(pkey, sd.digestOid)
|
encryptionOid, err := getOIDForEncryptionAlgorithm(pkey, sd.digestOid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
attrs := &attributes{}
|
finalAttrs, signature, err := sd.signWithAttributes(pkey, config)
|
||||||
attrs.Add(OIDAttributeContentType, sd.sd.ContentInfo.ContentType)
|
|
||||||
attrs.Add(OIDAttributeMessageDigest, sd.messageDigest)
|
|
||||||
attrs.Add(OIDAttributeSigningTime, time.Now().UTC())
|
|
||||||
for _, attr := range config.ExtraSignedAttributes {
|
|
||||||
attrs.Add(attr.Type, attr.Value)
|
|
||||||
}
|
|
||||||
finalAttrs, err := attrs.ForMarshalling()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// create signature of signed attributes
|
|
||||||
signature, err := signAttributes(finalAttrs, pkey, hasher)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -216,6 +197,34 @@ func (sd *SignedData) AddSignerChain(ee *smx509.Certificate, pkey crypto.Private
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sd *SignedData) signWithAttributes(pkey crypto.PrivateKey, config SignerInfoConfig) ([]attribute, []byte, error) {
|
||||||
|
hasher, err := getHashForOID(sd.digestOid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := newHash(hasher, sd.digestOid)
|
||||||
|
h.Write(sd.data)
|
||||||
|
messageDigest := h.Sum(nil)
|
||||||
|
|
||||||
|
attrs := &attributes{}
|
||||||
|
attrs.Add(OIDAttributeContentType, sd.sd.ContentInfo.ContentType)
|
||||||
|
attrs.Add(OIDAttributeMessageDigest, messageDigest)
|
||||||
|
attrs.Add(OIDAttributeSigningTime, time.Now().UTC())
|
||||||
|
for _, attr := range config.ExtraSignedAttributes {
|
||||||
|
attrs.Add(attr.Type, attr.Value)
|
||||||
|
}
|
||||||
|
finalAttrs, err := attrs.ForMarshalling()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
// create signature of signed attributes
|
||||||
|
signature, err := signAttributes(finalAttrs, pkey, hasher)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return finalAttrs, signature, nil
|
||||||
|
}
|
||||||
|
|
||||||
func newHash(hasher crypto.Hash, hashOid asn1.ObjectIdentifier) hash.Hash {
|
func newHash(hasher crypto.Hash, hashOid asn1.ObjectIdentifier) hash.Hash {
|
||||||
var h hash.Hash
|
var h hash.Hash
|
||||||
if hashOid.Equal(OIDDigestAlgorithmSM3) || hashOid.Equal(OIDDigestAlgorithmSM2SM3) {
|
if hashOid.Equal(OIDDigestAlgorithmSM3) || hashOid.Equal(OIDDigestAlgorithmSM2SM3) {
|
||||||
@ -240,20 +249,7 @@ func (sd *SignedData) SignWithoutAttr(ee *smx509.Certificate, pkey crypto.Privat
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key, ok := pkey.(crypto.Signer)
|
if signature, err = signData(sd.data, pkey, hasher); err != nil {
|
||||||
if !ok {
|
|
||||||
return errors.New("pkcs7: private key does not implement crypto.Signer")
|
|
||||||
}
|
|
||||||
_, isSM2 := pkey.(sm2.Signer)
|
|
||||||
if isSM2 {
|
|
||||||
signature, err = key.Sign(rand.Reader, sd.data, sm2.DefaultSM2SignerOpts)
|
|
||||||
} else {
|
|
||||||
h := newHash(hasher, sd.digestOid)
|
|
||||||
h.Write(sd.data)
|
|
||||||
sd.messageDigest = h.Sum(nil)
|
|
||||||
signature, err = key.Sign(rand.Reader, sd.messageDigest, hasher)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var ias issuerAndSerial
|
var ias issuerAndSerial
|
||||||
@ -380,20 +376,33 @@ func signAttributes(attrs []attribute, pkey crypto.PrivateKey, hasher crypto.Has
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return signData(attrBytes, pkey, hasher)
|
||||||
if key, ok := pkey.(sm2.Signer); ok {
|
|
||||||
return key.SignWithSM2(rand.Reader, nil, attrBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h := hasher.New()
|
// signData signs the provided data using the given private key and hash function.
|
||||||
h.Write(attrBytes)
|
// It returns the signed data or an error if the signing process fails.
|
||||||
hash := h.Sum(nil)
|
func signData(data []byte, pkey crypto.PrivateKey, hasher crypto.Hash) ([]byte, error) {
|
||||||
|
|
||||||
key, ok := pkey.(crypto.Signer)
|
key, ok := pkey.(crypto.Signer)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("pkcs7: private key does not implement crypto.Signer")
|
return nil, errors.New("pkcs7: private key does not implement crypto.Signer")
|
||||||
}
|
}
|
||||||
return key.Sign(rand.Reader, hash, hasher)
|
hash := data
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("pkcs7: unsupported hash function %s", hasher)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
h := hasher.New()
|
||||||
|
h.Write(data)
|
||||||
|
hash = h.Sum(nil)
|
||||||
|
}
|
||||||
|
return key.Sign(rand.Reader, hash, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// concats and wraps the certificates in the RawValue structure
|
// concats and wraps the certificates in the RawValue structure
|
||||||
|
@ -87,6 +87,7 @@ func testSign(t *testing.T, isSM bool, content []byte, sigalgs []x509.SignatureA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSign(t *testing.T) {
|
func TestSign(t *testing.T) {
|
||||||
content := []byte("Hello World")
|
content := []byte("Hello World")
|
||||||
sigalgs := []x509.SignatureAlgorithm{
|
sigalgs := []x509.SignatureAlgorithm{
|
||||||
|
@ -25,8 +25,17 @@ import (
|
|||||||
// should be performed.
|
// should be performed.
|
||||||
var directSigning crypto.Hash = 0
|
var directSigning crypto.Hash = 0
|
||||||
|
|
||||||
// Signer SM2 special signer
|
// Signer is an interface for an opaque private key that can be used for
|
||||||
|
// signing operations. For example, an SM2 key kept in a hardware module.
|
||||||
|
// Deprecated: please use crypto.Signer directly.
|
||||||
type Signer interface {
|
type Signer interface {
|
||||||
|
// Public returns the public key corresponding to the opaque,
|
||||||
|
// private key.
|
||||||
|
Public() crypto.PublicKey
|
||||||
|
|
||||||
|
// SignWithSM2 signs raw message with the private key, possibly using entropy from
|
||||||
|
// rand, and the user ID (UID). If the UID is not provided, a default UID (1234567812345678) is used.
|
||||||
|
// The signature is generated using the SM2 algorithm.
|
||||||
SignWithSM2(rand io.Reader, uid, msg []byte) ([]byte, error)
|
SignWithSM2(rand io.Reader, uid, msg []byte) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +659,6 @@ func randomPoint(c *sm2Curve, rand io.Reader, checkOrderMinus1 bool) (k *bigmod.
|
|||||||
// randomPoint rejects a candidate for being higher than the modulus.
|
// randomPoint rejects a candidate for being higher than the modulus.
|
||||||
var testingOnlyRejectionSamplingLooped func()
|
var testingOnlyRejectionSamplingLooped func()
|
||||||
|
|
||||||
|
|
||||||
// RecoverPublicKeysFromSM2Signature attempts to recover the public keys from an SM2 signature.
|
// RecoverPublicKeysFromSM2Signature attempts to recover the public keys from an SM2 signature.
|
||||||
// This function takes a hash and a signature as input and returns a slice of possible public keys
|
// This function takes a hash and a signature as input and returns a slice of possible public keys
|
||||||
// that could have generated the given signature.
|
// that could have generated the given signature.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user