aboutsummaryrefslogtreecommitdiff
path: root/signer.go
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-05-22 16:48:10 +0200
committerDimitri Sokolyuk <demon@dim13.org>2016-05-22 16:48:10 +0200
commitddd02682605ebad46cd36714981a6859c69f349e (patch)
treea2f12fee5118e6480fdfb0a0bb4a8bebf974f052 /signer.go
parent9664c9a60a10cf7a91fbf9e93b595f2155a9543a (diff)
Refactor signer
Diffstat (limited to 'signer.go')
-rw-r--r--signer.go49
1 files changed, 42 insertions, 7 deletions
diff --git a/signer.go b/signer.go
index 2ee0ed4..6829995 100644
--- a/signer.go
+++ b/signer.go
@@ -5,7 +5,9 @@ import (
"crypto/ecdsa"
"crypto/rsa"
"encoding/base64"
+ "errors"
"io"
+ "net/http"
"strings"
"github.com/square/go-jose"
@@ -14,14 +16,17 @@ import (
// KeySize is a default RSA key size
const KeySize = 2048
+var errNoNonces = errors.New("out of nonces")
+
// Signer ...
type Signer struct {
signer jose.Signer
thumb string
+ nonces chan string
}
func NewSigner(privKey crypto.PrivateKey) (*Signer, error) {
- thumb := func(alg string, pubKey crypto.PublicKey) (string, error) {
+ thumb := func(pubKey crypto.PublicKey, alg string) (string, error) {
wk := &jose.JsonWebKey{Key: pubKey, Algorithm: alg}
t, err := wk.Thumbprint(crypto.SHA256)
return base64.RawURLEncoding.EncodeToString(t), err
@@ -32,29 +37,59 @@ func NewSigner(privKey crypto.PrivateKey) (*Signer, error) {
if err != nil {
return nil, err
}
- t, err := thumb("RSA", k.Public())
+ t, err := thumb(k.Public(), "RSA")
if err != nil {
return nil, err
}
- return &Signer{signer: s, thumb: t}, nil
+ sig := &Signer{signer: s, thumb: t, nonces: make(chan string, 100)}
+ sig.signer.SetNonceSource(sig)
+ return sig, nil
case *ecdsa.PrivateKey:
s, err := jose.NewSigner(jose.ES384, k)
if err != nil {
return nil, err
}
- t, err := thumb("EC", k.Public())
+ t, err := thumb(k.Public(), "EC")
if err != nil {
return nil, err
}
- return &Signer{signer: s, thumb: t}, nil
+ sig := &Signer{signer: s, thumb: t, nonces: make(chan string, 100)}
+ sig.signer.SetNonceSource(sig)
+ return sig, nil
default:
return nil, ErrKeyType
}
}
+// Nonce implements jose nonce provider
+func (s Signer) Nonce() (string, error) {
+ select {
+ case nonce := <-s.nonces:
+ return nonce, nil
+ default:
+ return "", errNoNonces
+ }
+}
+
+// RoundTrip extracts nonces from HTTP response
+func (s Signer) RoundTrip(req *http.Request) (*http.Response, error) {
+ resp, err := http.DefaultTransport.RoundTrip(req)
+ if err != nil {
+ return nil, err
+ }
+ nonce := resp.Header.Get("Replay-Nonce")
+ if nonce == "" {
+ return nil, errNoNonces
+ }
+ if len(s.nonces) == cap(s.nonces) {
+ <-s.nonces // drop oldest
+ }
+ s.nonces <- nonce
+ return resp, nil
+}
+
// Sign implements Signer interface
-func (s Signer) Sign(msg []byte, n jose.NonceSource) (io.Reader, error) {
- s.signer.SetNonceSource(n)
+func (s Signer) Sign(msg []byte) (io.Reader, error) {
obj, err := s.signer.Sign(msg)
if err != nil {
return nil, err