-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsignopts.go
130 lines (108 loc) · 3.13 KB
/
signopts.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
// SPDX-FileCopyrightText: 2024 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0
package securly
import (
"crypto/x509"
"fmt"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jwk"
)
// SignOption is a functional option for the Instructions constructor.
type SignOption interface {
apply(*encoder) error
}
// SignWith sets the signing algorithm, public key, and private key used to sign
// the Message, as well as any intermediaries.
//
// The following combinations are valid (the public/private keys must match):
// - ES256, private: *ecdsa.PrivateKey
// - ES384, private: *ecdsa.PrivateKey
// - ES512, private: *ecdsa.PrivateKey
// - RS256, private: *rsa.PrivateKey
// - RS384, private: *rsa.PrivateKey
// - RS512, private: *rsa.PrivateKey
// - PS256, private: *rsa.PrivateKey
// - PS384, private: *rsa.PrivateKey
// - PS512, private: *rsa.PrivateKey
// - EdDSA, private: ed25519.PrivateKey
//
// Unfortunately, to make this work the private type needs to be an interface{}.
func SignWith(alg jwa.SignatureAlgorithm,
public *x509.Certificate, private jwk.Key,
intermediates ...*x509.Certificate,
) SignOption {
return signAlgOption{
alg: alg,
public: public,
key: private,
intermediates: intermediates,
}
}
func SignWithRaw(alg jwa.SignatureAlgorithm,
public *x509.Certificate, private any,
intermediates ...*x509.Certificate,
) SignOption {
key, err := jwk.FromRaw(private)
if err != nil {
return errorSign(err)
}
return SignWith(alg, public, key, intermediates...)
}
type signAlgOption struct {
alg jwa.SignatureAlgorithm
public *x509.Certificate
key jwk.Key
intermediates []*x509.Certificate
}
func (s signAlgOption) apply(enc *encoder) error {
if s.alg.IsSymmetric() || s.alg == jwa.NoSignature {
return ErrInvalidSignAlg
}
enc.signAlg = s.alg
enc.leaf = s.public
enc.key = s.key
enc.intermediates = s.intermediates
return nil
}
// NoSignature indicates that the Message should not be signed. It cannot be used
// with any SignWith options or an error will be returned. This is to ensure that
// the caller is aware that the Message will not be signed.
func NoSignature() SignOption {
return noSignatureOption{}
}
type noSignatureOption struct{}
func (n noSignatureOption) apply(enc *encoder) error {
enc.doNotSign = true
return nil
}
//------------------------------------------------------------------------------
func errorSign(err error) SignOption {
return errorSignOption{
err: err,
}
}
type errorSignOption struct {
err error
}
func (e errorSignOption) apply(*encoder) error {
return e.err
}
func validateSigAlg() SignOption {
return validateSigAlgOption{}
}
type validateSigAlgOption struct{}
func (v validateSigAlgOption) apply(enc *encoder) error {
if enc.doNotSign {
if enc.signAlg != "" ||
enc.leaf != nil ||
enc.key != nil ||
len(enc.intermediates) > 0 {
return fmt.Errorf("%w: NoSignature() must be used in isolation", ErrInvalidSignAlg)
}
return nil
}
if enc.signAlg == "" || enc.key == nil {
return fmt.Errorf("%w: algorithm and key are required", ErrInvalidSignAlg)
}
return nil
}