...
1 package signerverifier
2
3 import (
4 "context"
5 "crypto"
6 "crypto/ecdsa"
7 "crypto/rand"
8 "crypto/sha256"
9 "crypto/sha512"
10 "fmt"
11 "os"
12 )
13
14 const ECDSAKeyType = "ecdsa"
15
16
17
18 type ECDSASignerVerifier struct {
19 keyID string
20 curveSize int
21 private *ecdsa.PrivateKey
22 public *ecdsa.PublicKey
23 }
24
25
26
27 func NewECDSASignerVerifierFromSSLibKey(key *SSLibKey) (*ECDSASignerVerifier, error) {
28 if len(key.KeyVal.Public) == 0 {
29 return nil, ErrInvalidKey
30 }
31
32 _, publicParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Public))
33 if err != nil {
34 return nil, fmt.Errorf("unable to create ECDSA signerverifier: %w", err)
35 }
36
37 sv := &ECDSASignerVerifier{
38 keyID: key.KeyID,
39 curveSize: publicParsedKey.(*ecdsa.PublicKey).Params().BitSize,
40 public: publicParsedKey.(*ecdsa.PublicKey),
41 private: nil,
42 }
43
44 if len(key.KeyVal.Private) > 0 {
45 _, privateParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Private))
46 if err != nil {
47 return nil, fmt.Errorf("unable to create ECDSA signerverifier: %w", err)
48 }
49
50 sv.private = privateParsedKey.(*ecdsa.PrivateKey)
51 }
52
53 return sv, nil
54 }
55
56
57 func (sv *ECDSASignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
58 if sv.private == nil {
59 return nil, ErrNotPrivateKey
60 }
61
62 hashedData := getECDSAHashedData(data, sv.curveSize)
63
64 return ecdsa.SignASN1(rand.Reader, sv.private, hashedData)
65 }
66
67
68 func (sv *ECDSASignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
69 hashedData := getECDSAHashedData(data, sv.curveSize)
70
71 if ok := ecdsa.VerifyASN1(sv.public, hashedData, sig); !ok {
72 return ErrSignatureVerificationFailed
73 }
74
75 return nil
76 }
77
78
79
80 func (sv *ECDSASignerVerifier) KeyID() (string, error) {
81 return sv.keyID, nil
82 }
83
84
85
86 func (sv *ECDSASignerVerifier) Public() crypto.PublicKey {
87 return sv.public
88 }
89
90
91
92 func LoadECDSAKeyFromFile(path string) (*SSLibKey, error) {
93 contents, err := os.ReadFile(path)
94 if err != nil {
95 return nil, fmt.Errorf("unable to load ECDSA key from file: %w", err)
96 }
97
98 return LoadKeyFromSSLibBytes(contents)
99 }
100
101 func getECDSAHashedData(data []byte, curveSize int) []byte {
102 switch {
103 case curveSize <= 256:
104 return hashBeforeSigning(data, sha256.New())
105 case 256 < curveSize && curveSize <= 384:
106 return hashBeforeSigning(data, sha512.New384())
107 case curveSize > 384:
108 return hashBeforeSigning(data, sha512.New())
109 }
110 return []byte{}
111 }
112
View as plain text