diff --git a/README.md b/README.md index c3c8d5d5..f36ebd29 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Current features: - [x] Revoking Certificates - [ ] Initiating account recovery - Identifier validation challenges - - [x] SimpleHTTP Challenge + - [x] SimpleHTTP Challenge (Scheduled for removal on Nov 19th) - [x] HTTP (http-01) - [ ] TLS with Server Name Indication (tls-sni-01) - [ ] Proof of Possession of a Prior Key (proofOfPossession-01) diff --git a/acme/crypto.go b/acme/crypto.go index 608ec7d4..73bd9c99 100644 --- a/acme/crypto.go +++ b/acme/crypto.go @@ -9,6 +9,7 @@ import ( "crypto/rsa" "crypto/x509" "crypto/x509/pkix" + "encoding/base64" "encoding/binary" "encoding/pem" "errors" @@ -16,6 +17,7 @@ import ( "io/ioutil" "math/big" "net/http" + "strings" "time" "golang.org/x/crypto/ocsp" @@ -115,6 +117,27 @@ func GetOCSPForCert(bundle []byte) ([]byte, int, error) { return ocspResBytes, ocspRes.Status, nil } +func getKeyAuthorization(token string, key interface{}) (string, error) { + // Generate the Key Authorization for the challenge + jwk := keyAsJWK(key) + if jwk == nil { + return "", errors.New("Could not generate JWK from key.") + } + thumbBytes, err := jwk.Thumbprint(crypto.SHA256) + if err != nil { + return "", err + } + + // unpad the base64URL + keyThumb := base64.URLEncoding.EncodeToString(thumbBytes) + index := strings.Index(keyThumb, "=") + if index != -1 { + keyThumb = keyThumb[:index] + } + + return token + "." + keyThumb, nil +} + // Derive the shared secret according to acme spec 5.6 func performECDH(priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, outLen int, label string) []byte { // Derive Z from the private and public keys according to SEC 1 Ver. 2.0 - 3.3.1 diff --git a/acme/http_challenge.go b/acme/http_challenge.go index f0a2d3cc..66ade473 100644 --- a/acme/http_challenge.go +++ b/acme/http_challenge.go @@ -1,8 +1,6 @@ package acme import ( - "crypto" - "encoding/base64" "encoding/json" "errors" "fmt" @@ -27,19 +25,11 @@ func (s *httpChallenge) Solve(chlng challenge, domain string) error { s.end = make(chan error) // Generate the Key Authorization for the challenge - key := keyAsJWK(&s.jws.privKey.PublicKey) - thumbBytes, err := key.Thumbprint(crypto.SHA256) + keyAuth, err := getKeyAuthorization(chlng.Token, &s.jws.privKey.PublicKey) if err != nil { return err } - keyThumb := base64.URLEncoding.EncodeToString(thumbBytes) - index := strings.Index(keyThumb, "=") - if index != -1 { - keyThumb = keyThumb[:index] - } - keyAuth := chlng.Token + "." + keyThumb - go s.startHTTPServer(domain, chlng.Token, keyAuth) var listener net.Listener select {