-
Notifications
You must be signed in to change notification settings - Fork 0
/
sm2.go
executable file
·102 lines (82 loc) · 2.45 KB
/
sm2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package cncc
import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/asn1"
"errors"
"fmt"
"math/big"
"github.com/tjfoc/gmsm/sm2"
)
/**
* @Author: WeiBingtao/13156050650@163.com
* @Version: 1.0
* @Description:
* @Date: 2020/9/15 上午11:30
*/
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
type SM2Signature struct {
R, S *big.Int
}
var (
// curveHalfOrders contains the precomputed curve group orders halved.
// It is used to ensure that signature' S value is lower or equal to the
// curve group order halved. We accept only low-S signatures.
// They are precomputed for efficiency reasons.
curveHalfOrders map[elliptic.Curve]*big.Int = map[elliptic.Curve]*big.Int{
elliptic.P224(): new(big.Int).Rsh(elliptic.P224().Params().N, 1),
elliptic.P256(): new(big.Int).Rsh(elliptic.P256().Params().N, 1),
elliptic.P384(): new(big.Int).Rsh(elliptic.P384().Params().N, 1),
elliptic.P521(): new(big.Int).Rsh(elliptic.P521().Params().N, 1),
sm2.P256Sm2(): new(big.Int).Rsh(sm2.P256Sm2().Params().N, 1),
}
)
func MarshalSM2Signature(r, s *big.Int) ([]byte, error) {
return asn1.Marshal(SM2Signature{r, s})
}
func UnmarshalSM2Signature(raw []byte) (*big.Int, *big.Int, error) {
// Unmarshal
sig := new(SM2Signature)
_, err := asn1.Unmarshal(raw, sig)
if err != nil {
return nil, nil, fmt.Errorf("Failed unmashalling signature [%s]", err)
}
// Validate sig
if sig.R == nil {
return nil, nil, errors.New("Invalid signature. R must be different from nil.")
}
if sig.S == nil {
return nil, nil, errors.New("Invalid signature. S must be different from nil.")
}
if sig.R.Sign() != 1 {
return nil, nil, errors.New("Invalid signature. R must be larger than zero")
}
if sig.S.Sign() != 1 {
return nil, nil, errors.New("Invalid signature. S must be larger than zero")
}
return sig.R, sig.S, nil
}
func ToLowS(k *ecdsa.PublicKey, s *big.Int) (*big.Int, bool, error) {
lowS, err := IsLowS(k, s)
if err != nil {
return nil, false, err
}
if !lowS && k.Curve != sm2.P256Sm2() {
// Set s to N - s that will be then in the lower part of signature space
// less or equal to half order
s.Sub(k.Params().N, s)
return s, true, nil
}
return s, false, nil
}
// IsLow checks that s is a low-S
func IsLowS(k *ecdsa.PublicKey, s *big.Int) (bool, error) {
halfOrder, ok := curveHalfOrders[k.Curve]
if !ok {
return false, fmt.Errorf("Curve not recognized [%s]", k.Curve)
}
return s.Cmp(halfOrder) != 1, nil
}