-
Notifications
You must be signed in to change notification settings - Fork 282
/
signer.go
153 lines (130 loc) · 3.16 KB
/
signer.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache version 2.0 license. See LICENSE file for terms.
package zmssvctoken
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"fmt"
"math/big"
"strings"
)
var hash = crypto.SHA256
// signer signs a string and returns the signature
type signer interface {
sign(input string) (string, error)
}
// verifier verifies the signature for a string
type verifier interface {
verify(input, signature string) error
}
// hashString hashes the input string using the
// standard hash algo
func hashString(input string) ([]byte, error) {
h := hash.New()
_, err := h.Write([]byte(input))
if err != nil {
return nil, err
}
return h.Sum(nil), nil
}
func newSigner(privateKeyPEM []byte) (signer, error) {
block, _ := pem.Decode(privateKeyPEM)
if block == nil {
return nil, fmt.Errorf("Unable to load private key")
}
switch block.Type {
case "EC PRIVATE KEY":
key, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return &sign{key: key}, nil
case "RSA PRIVATE KEY":
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return &sign{key: key}, nil
default:
return nil, fmt.Errorf("Unsupported private key type: %s", block.Type)
}
}
type sign struct {
key crypto.Signer
}
func (s *sign) sign(input string) (string, error) {
hashed, err := hashString(input)
if err != nil {
return "", err
}
signed, err := s.key.Sign(rand.Reader, hashed, hash)
if err != nil {
return "", err
}
return new(yBase64).EncodeToString(signed), nil
}
type internalVerifier interface {
verify(hashed []byte, sig []byte) error
}
type rsaVerify struct {
key *rsa.PublicKey
}
func (r *rsaVerify) verify(hashed []byte, sig []byte) error {
return rsa.VerifyPKCS1v15(r.key, hash, hashed, sig)
}
type ecdsaVerify struct {
key *ecdsa.PublicKey
}
func (e *ecdsaVerify) verify(hashed []byte, sig []byte) error {
var s struct {
R, S *big.Int
}
_, err := asn1.Unmarshal(sig, &s)
if err != nil {
return fmt.Errorf("Unable to unmarshal ECDSA sig, %v", err)
}
if ok := ecdsa.Verify(e.key, hashed, s.R, s.S); !ok {
return fmt.Errorf("Invalid ECDSA signature")
}
return nil
}
func newVerifier(publicKeyPEM []byte) (verifier, error) {
block, _ := pem.Decode(publicKeyPEM)
if block == nil {
return nil, fmt.Errorf("Unable to load public key")
}
if !strings.HasSuffix(block.Type, "PUBLIC KEY") {
return nil, fmt.Errorf("Invalid public key type: %s", block.Type)
}
xkey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
switch key := xkey.(type) {
case *rsa.PublicKey:
return &verify{iv: &rsaVerify{key: key}}, nil
case *ecdsa.PublicKey:
return &verify{iv: &ecdsaVerify{key: key}}, nil
default:
return nil, fmt.Errorf("Unsupported key type, not RSA or ECDSA")
}
}
type verify struct {
iv internalVerifier
}
func (v *verify) verify(input, signature string) error {
sigBytes, err := new(yBase64).DecodeString(signature)
if err != nil {
return err
}
hashed, err := hashString(input)
if err != nil {
return err
}
return v.iv.verify(hashed, sigBytes)
}