aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2015-12-04 17:40:32 +0100
committerDimitri Sokolyuk <demon@dim13.org>2015-12-04 17:40:32 +0100
commit605b1310fb6e1c1fa1382df76a1d52954fc82ba7 (patch)
treec5228d10b35829114f375ef37e1be43a1a2b0047
parentb87c51d9fd46e446c620b13bf8e8c91f665fe8f4 (diff)
Update Signer
-rw-r--r--account.go38
-rw-r--r--client.go57
-rw-r--r--cmd/acme/main.go27
-rw-r--r--directory.go7
-rw-r--r--messages.go19
-rw-r--r--nonce.go28
6 files changed, 98 insertions, 78 deletions
diff --git a/account.go b/account.go
index 7766893..1fd0efd 100644
--- a/account.go
+++ b/account.go
@@ -3,7 +3,9 @@ package acme
import (
"crypto/rand"
"crypto/rsa"
+ "errors"
"fmt"
+ "net/http"
"net/mail"
"github.com/square/go-jose"
@@ -12,34 +14,36 @@ import (
type Account struct {
Contact []string `json:"contact"`
PrivKey *rsa.PrivateKey `json:"key"`
- Signer jose.Signer `json:"-"`
+ signer jose.Signer
+ nonce chan string
}
-func NewAccount(email string, bits int) (Account, error) {
+func NewAccount(email string, bits int) (*Account, error) {
m, err := mail.ParseAddress(email)
if err != nil {
- return Account{}, err
+ return nil, err
}
key, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
- return Account{}, err
+ return nil, err
}
- return Account{
+ return &Account{
Contact: []string{"mailto:" + m.Address},
PrivKey: key,
+ nonce: make(chan string, 100),
}, nil
}
func (a *Account) Sign(msg []byte) ([]byte, error) {
- if a.Signer == nil {
+ if a.signer == nil {
signer, err := jose.NewSigner(jose.RS256, a.PrivKey)
if err != nil {
return nil, err
}
- signer.SetNonceSource(nonces)
- a.Signer = signer
+ signer.SetNonceSource(a)
+ a.signer = signer
}
- obj, err := a.Signer.Sign(msg)
+ obj, err := a.signer.Sign(msg)
return []byte(obj.FullSerialize()), err
}
@@ -51,3 +55,19 @@ func (a *Account) ParseSigned(msg []byte) ([]byte, error) {
}
return obj.Verify(&a.PrivKey.PublicKey)
}
+
+var errNoNonces = errors.New("No nonces available")
+
+// Nonce implements jose nonce provider
+func (a Account) Nonce() (string, error) {
+ if nonce, ok := <-a.nonce; ok {
+ return nonce, nil
+ }
+ return "", errNoNonces
+}
+
+func (a Account) parseNonce(r *http.Response) {
+ if nonce := r.Header.Get("Replay-Nonce"); nonce != "" {
+ a.nonce <- nonce
+ }
+}
diff --git a/client.go b/client.go
index b596906..27551ba 100644
--- a/client.go
+++ b/client.go
@@ -3,27 +3,52 @@ package acme
import (
"bytes"
"encoding/json"
+ "errors"
"log"
"net/http"
"net/textproto"
"regexp"
+)
+
+type Status int
- "github.com/square/go-jose"
+const (
+ StatusUnknown Status = iota
+ StatusPending
+ StatusProcessing
+ StatusValid
+ StatusInvalid
+ StatusRevoked
)
+func (s *Status) UnmarshalJSON(b []byte) error {
+ var status = map[string]Status{
+ "unknown": StatusUnknown,
+ "pending": StatusPending,
+ "processing": StatusProcessing,
+ "valid": StatusValid,
+ "invalid": StatusInvalid,
+ "revoked": StatusRevoked,
+ }
+ if st, ok := status[string(b)]; ok {
+ *s = st
+ return nil
+ }
+ return errors.New("unknown status")
+}
+
type Signer interface {
Sign([]byte) ([]byte, error)
+ parseNonce(*http.Response)
}
-var nonces = newNonce()
-
-func Get(uri string, v interface{}) error {
+func Get(s Signer, uri string, v interface{}) error {
resp, err := http.Get(uri)
if err != nil {
return err
}
defer resp.Body.Close()
- nonces.parse(resp)
+ s.parseNonce(resp)
return json.NewDecoder(resp.Body).Decode(v)
}
@@ -43,31 +68,21 @@ func Post(s Signer, uri string, v interface{}) (*http.Response, error) {
return nil, err
}
- resp, err := http.Post(uri, "application/jose+json", bytes.NewReader(signed))
+ resp, err := http.Post(uri, "application/jose+json",
+ bytes.NewReader(signed))
if err != nil {
return nil, err
}
- nonces.parse(resp)
- log.Printf("%+v\n", parseLinks(resp))
+
+ s.parseNonce(resp)
if resp.StatusCode >= http.StatusBadRequest {
return nil, handleError(resp)
}
- return resp, nil
-}
+ log.Printf("%+v\n", parseLinks(resp))
-func Sign(acc Account, body []byte) (string, error) {
- signer, err := jose.NewSigner(jose.RS256, acc.PrivKey)
- signer.SetNonceSource(nonces)
- if err != nil {
- return "", err
- }
- obj, err := signer.Sign(body)
- if err != nil {
- return "", err
- }
- return obj.FullSerialize(), nil
+ return resp, nil
}
func parseLinks(r *http.Response) map[string]string {
diff --git a/cmd/acme/main.go b/cmd/acme/main.go
index c6250e6..687fd6f 100644
--- a/cmd/acme/main.go
+++ b/cmd/acme/main.go
@@ -1,7 +1,9 @@
package main
import (
+ "encoding/json"
"flag"
+ "io/ioutil"
"log"
"dim13.org/acme"
@@ -23,13 +25,11 @@ var (
port = flag.Int("port", 8443, "port to listen")
)
-func main() {
+func init() {
flag.Parse()
+}
- dir, err := acme.NewDirectory(*server)
- must(err)
- acme.Print(dir)
-
+func main() {
acc, err := acme.NewAccount(eMail, keySize)
must(err)
acme.Print(acc)
@@ -38,7 +38,22 @@ func main() {
must(err)
acme.SaveKey(".acme/priv.pem", acc.PrivKey)
- resp, err := acme.Post(&acc, dir.NewReg, acme.NewRegistration(acc.Contact, acme.NewReg{}))
+ dir := acme.Directory{}
+ err = acme.Get(acc, *server, &dir)
+ must(err)
+ acme.Print(dir)
+
+ resp, err := acme.Post(acc, dir.NewReg, acme.NewRegistration(acc.Contact, acme.NewReg{}))
must(err)
log.Println(resp)
+
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ must(err)
+ log.Println(string(body))
+
+ rr := acme.RegistrationResp{}
+ err = json.Unmarshal(body, &rr)
+ must(err)
+ log.Printf("%+v\n", rr)
}
diff --git a/directory.go b/directory.go
deleted file mode 100644
index 44062f5..0000000
--- a/directory.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package acme
-
-func NewDirectory(uri string) (Directory, error) {
- var dir Directory
- err := Get(uri, &dir)
- return dir, err
-}
diff --git a/messages.go b/messages.go
index cb10a79..b5a1738 100644
--- a/messages.go
+++ b/messages.go
@@ -1,5 +1,10 @@
package acme
+import (
+ "net"
+ "time"
+)
+
const (
// LEV1 Let's Encrytpt V1
LEV1 = `https://acme-v01.api.letsencrypt.org/directory`
@@ -27,11 +32,11 @@ type Registration struct {
// RegistrationResp ...
type RegistrationResp struct {
- ID int `json:"id"`
- Key Key `json:"key"`
- Contact []string `json:"contact"`
- InitialIP string `json:"initalIp"` // not in draft
- CreatedAt string `json:"createdAt"` // 2006-01-02T15:04:05.999999999Z
+ ID int `json:"id"`
+ Key Key `json:"key"`
+ Contact []string `json:"contact"`
+ InitialIP net.IP `json:"initialIp"` // not in draft
+ CreatedAt time.Time `json:"createdAt"` // 2006-01-02T15:04:05.999999999Z
}
// Key contains public part of jose.JsonWebKey
@@ -50,7 +55,7 @@ type Authorization struct {
// AuthorizationResp Objects
type AuthorizationResp struct {
Identifier Identifier `json:"identifier"`
- Status string `json:"status,omitemtpy"` // e.g. valid
+ Status Status `json:"status,omitemtpy"` // e.g. valid
Expires string `json:"expires,omitempty"` // 2006-01-02
Challenges []Challenge `json:"challenges"`
Combinations [][]int `json:"combinations,omitemtpy"`
@@ -65,7 +70,7 @@ type Identifier struct {
// Challege ...
type Challege struct {
Type string `json:"type"` // http-01
- Status string `json:"status"` // e.g. valid
+ Status Status `json:"status"` // e.g. valid
Validated string `json:"validated"` // 2006-01-02T15:04Z
KeyAuthorization string `json:"keyAuthorization"`
}
diff --git a/nonce.go b/nonce.go
deleted file mode 100644
index 88e67ca..0000000
--- a/nonce.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package acme
-
-import (
- "errors"
- "net/http"
-)
-
-var errNoNonces = errors.New("No nonces available")
-
-type nonce chan string
-
-func newNonce() nonce {
- return make(nonce, 100)
-}
-
-func (n nonce) parse(r *http.Response) {
- if nonce := r.Header.Get("Replay-Nonce"); nonce != "" {
- n <- nonce
- }
-}
-
-// Nonce implements jose nonce provider
-func (n nonce) Nonce() (string, error) {
- if nonce, ok := <-n; ok {
- return nonce, nil
- }
- return "", errNoNonces
-}