-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
ecdsa.go
134 lines (110 loc) · 4.27 KB
/
ecdsa.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package encrypt
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"io"
"math/big"
"strings"
"github.com/pkg/errors"
)
// EncodeECDSAPrivateKey encode ecdsa private key to pem bytes
func EncodeECDSAPrivateKey(privateKey *ecdsa.PrivateKey) ([]byte, error) {
x509Encoded, err := x509.MarshalECPrivateKey(privateKey)
if err != nil {
return nil, errors.Wrap(err, "marshal ecdsa private key")
}
return pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded}), nil
}
// EncodeECDSAPublicKey encode ecdsa public key to pem bytes
func EncodeECDSAPublicKey(publicKey *ecdsa.PublicKey) ([]byte, error) {
x509EncodedPub, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, errors.Wrap(err, "marshal ecdsa public key")
}
return pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: x509EncodedPub}), nil
}
// DecodeECDSAPrivateKey decode ecdsa private key from pem bytes
func DecodeECDSAPrivateKey(pemEncoded []byte) (*ecdsa.PrivateKey, error) {
block, _ := pem.Decode(pemEncoded)
privateKey, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return nil, errors.Wrap(err, "parse ecdsa private key")
}
return privateKey, nil
}
// DecodeECDSAPublicKey decode ecdsa public key from pem bytes
func DecodeECDSAPublicKey(pemEncodedPub []byte) (*ecdsa.PublicKey, error) {
blockPub, _ := pem.Decode(pemEncodedPub)
genericPublicKey, err := x509.ParsePKIXPublicKey(blockPub.Bytes)
if err != nil {
return nil, errors.Wrap(err, "parse ecdsa public key")
}
return genericPublicKey.(*ecdsa.PublicKey), nil
}
// SignByECDSAWithSHA256 generate signature by ecdsa private key use sha256
func SignByECDSAWithSHA256(priKey *ecdsa.PrivateKey, content []byte) (r, s *big.Int, err error) {
hash := sha256.Sum256(content)
return ecdsa.Sign(rand.Reader, priKey, hash[:])
}
// VerifyByECDSAWithSHA256 verify signature by ecdsa public key use sha256
func VerifyByECDSAWithSHA256(pubKey *ecdsa.PublicKey, content []byte, r, s *big.Int) bool {
hash := sha256.Sum256(content)
return ecdsa.Verify(pubKey, hash[:], r, s)
}
// SignReaderByECDSAWithSHA256 generate signature by ecdsa private key use sha256
func SignReaderByECDSAWithSHA256(priKey *ecdsa.PrivateKey, reader io.Reader) (r, s *big.Int, err error) {
hasher := sha256.New()
if _, err = io.Copy(hasher, reader); err != nil {
return nil, nil, errors.Wrap(err, "read content")
}
return ecdsa.Sign(rand.Reader, priKey, hasher.Sum(nil))
}
// VerifyReaderByECDSAWithSHA256 verify signature by ecdsa public key use sha256
func VerifyReaderByECDSAWithSHA256(pubKey *ecdsa.PublicKey, reader io.Reader, r, s *big.Int) (bool, error) {
hasher := sha256.New()
if _, err := io.Copy(hasher, reader); err != nil {
return false, errors.Wrap(err, "read content")
}
return ecdsa.Verify(pubKey, hasher.Sum(nil), r, s), nil
}
const ecdsaSignDelimiter = "."
// EncodeES256SignByHex format ecdsa sign to stirng
func EncodeES256SignByHex(a, b *big.Int) string {
return FormatBig2Hex(a) + ecdsaSignDelimiter + FormatBig2Hex(b)
}
// DecodeES256SignByHex parse ecdsa signature string to two *big.Int
func DecodeES256SignByHex(sign string) (a, b *big.Int, err error) {
ss := strings.Split(sign, ecdsaSignDelimiter)
if len(ss) != 2 {
return nil, nil, errors.Errorf("unknown format of signature `%s`, want `xxx.xxx`", sign)
}
var ok bool
if a, ok = ParseHex2Big(ss[0]); !ok {
return nil, nil, errors.Errorf("invalidate hex `%s`", ss[0])
}
if b, ok = ParseHex2Big(ss[1]); !ok {
return nil, nil, errors.Errorf("invalidate hex `%s`", ss[1])
}
return
}
// EncodeES256SignByBase64 format ecdsa signature to stirng
func EncodeES256SignByBase64(a, b *big.Int) string {
return FormatBig2Base64(a) + ecdsaSignDelimiter + FormatBig2Base64(b)
}
// DecodeES256SignByBase64 parse ecdsa signature string to two *big.Int
func DecodeES256SignByBase64(sign string) (a, b *big.Int, err error) {
ss := strings.Split(sign, ecdsaSignDelimiter)
if len(ss) != 2 {
return nil, nil, errors.Wrapf(err, "unknown format of signature `%s`, expect is `xxxx.xxxx`", sign)
}
if a, err = ParseBase642Big(ss[0]); err != nil {
return nil, nil, errors.Wrapf(err, "`%s` is not validate base64", ss[0])
}
if b, err = ParseBase642Big(ss[1]); err != nil {
return nil, nil, errors.Wrapf(err, "`%s` is not validate base64", ss[1])
}
return
}