/
ecdsa.go
110 lines (92 loc) · 2.89 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
package signerverifier
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"fmt"
"os"
)
const (
ECDSAKeyType = "ecdsa"
ECDSAKeyScheme = "ecdsa-sha2-nistp256"
)
// ECDSASignerVerifier is a dsse.SignerVerifier compliant interface to sign and
// verify signatures using ECDSA keys.
type ECDSASignerVerifier struct {
keyID string
curveSize int
private *ecdsa.PrivateKey
public *ecdsa.PublicKey
}
// NewECDSASignerVerifierFromSSLibKey creates an ECDSASignerVerifier from an
// SSLibKey.
func NewECDSASignerVerifierFromSSLibKey(key *SSLibKey) (*ECDSASignerVerifier, error) {
if len(key.KeyVal.Public) == 0 {
return nil, ErrInvalidKey
}
_, publicParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Public))
if err != nil {
return nil, fmt.Errorf("unable to create ECDSA signerverifier: %w", err)
}
sv := &ECDSASignerVerifier{
keyID: key.KeyID,
curveSize: publicParsedKey.(*ecdsa.PublicKey).Params().BitSize,
public: publicParsedKey.(*ecdsa.PublicKey),
private: nil,
}
return sv, nil
}
// Sign creates a signature for `data`.
func (sv *ECDSASignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
if sv.private == nil {
return nil, ErrNotPrivateKey
}
hashedData := getECDSAHashedData(data, sv.curveSize)
return ecdsa.SignASN1(rand.Reader, sv.private, hashedData)
}
// Verify verifies the `sig` value passed in against `data`.
func (sv *ECDSASignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
hashedData := getECDSAHashedData(data, sv.curveSize)
if ok := ecdsa.VerifyASN1(sv.public, hashedData, sig); !ok {
return ErrSignatureVerificationFailed
}
return nil
}
// KeyID returns the identifier of the key used to create the
// ECDSASignerVerifier instance.
func (sv *ECDSASignerVerifier) KeyID() (string, error) {
return sv.keyID, nil
}
// Public returns the public portion of the key used to create the
// ECDSASignerVerifier instance.
func (sv *ECDSASignerVerifier) Public() crypto.PublicKey {
return sv.public
}
// LoadECDSAKeyFromFile returns an SSLibKey instance for an ECDSA key stored in
// a file in the custom securesystemslib format.
//
// Deprecated: use LoadKey(). The custom serialization format has been
// deprecated. Use
// https://github.com/secure-systems-lab/securesystemslib/blob/main/docs/migrate_key.py
// to convert your key.
func LoadECDSAKeyFromFile(path string) (*SSLibKey, error) {
contents, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("unable to load ECDSA key from file: %w", err)
}
return LoadKeyFromSSLibBytes(contents)
}
func getECDSAHashedData(data []byte, curveSize int) []byte {
switch {
case curveSize <= 256:
return hashBeforeSigning(data, sha256.New())
case 256 < curveSize && curveSize <= 384:
return hashBeforeSigning(data, sha512.New384())
case curveSize > 384:
return hashBeforeSigning(data, sha512.New())
}
return []byte{}
}