-
Notifications
You must be signed in to change notification settings - Fork 25
/
rsa_pss.go
108 lines (93 loc) · 3.08 KB
/
rsa_pss.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
package csjwt
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"github.com/corestoreio/errors"
)
// SigningMethodRSAPSS implements the RSAPSS family of signing methods signing
// methods.
type SigningMethodRSAPSS struct {
SigningMethodRSA
Options rsa.PSSOptions
}
func newSigningMethodRSAPSS(n string, h crypto.Hash) *SigningMethodRSAPSS {
return &SigningMethodRSAPSS{
SigningMethodRSA{
Name: n,
Hash: h,
},
rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
Hash: h,
},
}
}
// NewSigningMethodPS256 creates a new 256bit RSAPSS SHA instance and registers
// it.
func NewSigningMethodPS256() *SigningMethodRSAPSS {
return newSigningMethodRSAPSS(PS256, crypto.SHA256)
}
// NewSigningMethodPS384 creates a new 384bit RSAPSS SHA instance and registers
// it.
func NewSigningMethodPS384() *SigningMethodRSAPSS {
return newSigningMethodRSAPSS(PS384, crypto.SHA384)
}
// NewSigningMethodPS512 creates a new 512bit RSAPSS SHA instance and registers
// it.
func NewSigningMethodPS512() *SigningMethodRSAPSS {
return newSigningMethodRSAPSS(PS512, crypto.SHA512)
}
// Verify implements the Verify method from SigningMethod interface. For the key
// you can use any of the WithRSA*Key*() functions. Error behaviour: Empty,
// NotImplemented, WriteFailed, NotValid
func (m *SigningMethodRSAPSS) Verify(signingString, signature []byte, key Key) error {
if key.Error != nil {
return errors.WithStack(key.Error)
}
if key.rsaKeyPub == nil {
return errors.Empty.Newf(errRSAPublicKeyEmpty)
}
// Decode the signature
sig, err := DecodeSegment(signature)
if err != nil {
return errors.WithStack(err)
}
// Create hasher
if !m.Hash.Available() {
return errors.NotImplemented.Newf(errRSAHashUnavailable)
}
hasher := m.Hash.New()
if _, err := hasher.Write(signingString); err != nil {
return errors.WriteFailed.New(err, "[csjwt] SigningMethodRSA.Verify.hasher.Write")
}
if err := rsa.VerifyPSS(key.rsaKeyPub, m.Hash, hasher.Sum(nil), sig, &m.Options); err != nil {
return errors.NotValid.New(err, "[csjwt] SigningMethodRSAPSS.Verify.VerifyPSS")
}
return nil
}
// Sign implements the Sign method from SigningMethod interface. For the key you
// can use any of the WithRSAPrivateKey*() functions. Error behaviour: Empty,
// NotImplemented, WriteFailed, NotValid.
func (m *SigningMethodRSAPSS) Sign(signingString []byte, key Key) ([]byte, error) {
if key.Error != nil {
return nil, errors.Wrap(key.Error, "[csjwt] SigningMethodRSAPSS.Sign.key")
}
if key.rsaKeyPriv == nil {
return nil, errors.Empty.Newf(errRSAPrivateKeyEmpty)
}
// Create the hasher
if !m.Hash.Available() {
return nil, errors.NotImplemented.Newf(errRSAHashUnavailable)
}
hasher := m.Hash.New()
if _, err := hasher.Write(signingString); err != nil {
return nil, errors.WriteFailed.New(err, "[csjwt] SigningMethodRSA.Sign.hasher.Write")
}
// Sign the string and return the encoded bytes
sigBytes, err := rsa.SignPSS(rand.Reader, key.rsaKeyPriv, m.Hash, hasher.Sum(nil), &m.Options)
if err != nil {
return nil, errors.NotValid.New(err, "[csjwt] SigningMethodRSAPSS.Sign.SignPSS")
}
return EncodeSegment(sigBytes), nil
}