From ddd02682605ebad46cd36714981a6859c69f349e Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 22 May 2016 16:48:10 +0200 Subject: Refactor signer --- provider.go | 39 +++++++++------------------------------ signer.go | 49 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/provider.go b/provider.go index 78855f0..5c43655 100644 --- a/provider.go +++ b/provider.go @@ -1,6 +1,7 @@ package acme import ( + "crypto" "encoding/json" "errors" "io/ioutil" @@ -47,12 +48,10 @@ type Meta struct { // Provider ... type Provider struct { Directory - nonces chan string http.Client } var ( - errNoNonces = errors.New("out of nonces") errContentType = errors.New("unknown content type") errChalType = errors.New("unknown challenge") errStatus = errors.New("unexpected status") @@ -67,37 +66,17 @@ const ( poll = time.Second ) -// RoundTrip extracts nonces from HTTP reponse -func (p *Provider) RoundTrip(req *http.Request) (*http.Response, error) { - resp, err := http.DefaultTransport.RoundTrip(req) +// DialProvider fetches directory and initializes first nonce +func DialProvider(directory string, key crypto.PrivateKey) (*Provider, error) { + sig, err := NewSigner(key) if err != nil { return nil, err } - nonce := resp.Header.Get("Replay-Nonce") - if nonce == "" { - return nil, errNoNonces - } - if len(p.nonces) == cap(p.nonces) { - <-p.nonces // drop oldest - } - p.nonces <- nonce - return resp, nil -} - -// Nonce implements jose nonce provider -func (p *Provider) Nonce() (string, error) { - select { - case nonce := <-p.nonces: - return nonce, nil - case <-time.After(timeout): - return "", errNoNonces + p := &Provider{ + Client: http.Client{ + Transport: sig, + }, } -} - -// DialProvider fetches directory and initializes first nonce -func DialProvider(directory string) (*Provider, error) { - p := &Provider{nonces: make(chan string, 100)} - p.Client = http.Client{Transport: p} if directory == "" { directory = LE1 } @@ -113,7 +92,7 @@ func (p *Provider) post(uri string, s *Signer, v interface{}) (*http.Response, e if err != nil { return nil, err } - signed, err := s.Sign(msg, p) + signed, err := s.Sign(msg) if err != nil { return nil, err } 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 -- cgit v1.2.3