-
Notifications
You must be signed in to change notification settings - Fork 0
/
sign.go
140 lines (116 loc) · 2.69 KB
/
sign.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
135
136
137
138
139
// Copyright 2024 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"crypto"
"crypto/rand"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rsa"
"strings"
"errors"
"fmt"
"reflect"
cose "github.com/veraison/go-cose"
"github.com/lestrrat-go/jwx/v2/jwk"
)
const (
HeaderLabelMeta = int64(8)
noAlg = cose.Algorithm(-65537)
)
func coseSignerFromJWK(j []byte) (cose.Signer, error) {
alg, key, err := getAlgAndKeyFromJWK(j)
if err != nil {
return nil, err
}
return cose.NewSigner(alg, key)
}
func getAlgAndKeyFromJWK(j []byte) (cose.Algorithm, crypto.Signer, error) {
var (
err error
k jwk.Key
crv elliptic.Curve
alg cose.Algorithm
)
k, err = jwk.ParseKey(j)
if err != nil {
return noAlg, nil, err
}
var key crypto.Signer
err = k.Raw(&key)
if err != nil {
return noAlg, nil, err
}
switch v := key.(type) {
case *ecdsa.PrivateKey:
alg = ellipticCurveToAlg(v.Curve)
if alg == noAlg {
return noAlg, nil, fmt.Errorf("unknown elliptic curve %v", crv)
}
case ed25519.PrivateKey:
alg = cose.AlgorithmEd25519
case *rsa.PrivateKey:
alg = rsaJWKToAlg(k)
if alg == noAlg {
return noAlg, nil, fmt.Errorf("unknown RSA algorithm %q", k.Algorithm().String())
}
default:
return noAlg, nil, fmt.Errorf("unknown private key type %v", reflect.TypeOf(key))
}
return alg, key, nil
}
func ellipticCurveToAlg(c elliptic.Curve) cose.Algorithm {
switch c {
case elliptic.P256():
return cose.AlgorithmES256
case elliptic.P384():
return cose.AlgorithmES384
case elliptic.P521():
return cose.AlgorithmES512
default:
return noAlg
}
}
func rsaJWKToAlg(k jwk.Key) cose.Algorithm {
switch k.Algorithm().String() {
case "PS256":
return cose.AlgorithmPS256
case "PS384":
return cose.AlgorithmPS384
case "PS512":
return cose.AlgorithmPS512
default:
return noAlg
}
}
func sign(
payload []byte,
meta []byte,
contentType string,
signer cose.Signer,
) ([]byte, error) {
if signer == nil {
return nil, errors.New("nil signer")
}
message := cose.NewSign1Message()
message.Payload = payload
alg := signer.Algorithm()
if strings.Contains(alg.String(), "unknown algorithm value") {
return nil, errors.New("signer has no algorithm")
}
message.Headers.Protected.SetAlgorithm(alg)
message.Headers.Protected[cose.HeaderLabelContentType] = contentType
if meta != nil {
message.Headers.Protected[HeaderLabelMeta] = meta
}
err := message.Sign(rand.Reader, []byte(""), signer)
if err != nil {
return nil, fmt.Errorf("COSE Sign1 signature failed: %w", err)
}
wrap, err := message.MarshalCBOR()
if err != nil {
return nil, fmt.Errorf("signed-corim marshaling failed: %w", err)
}
return wrap, nil
}