diff --git a/mockid.go b/mockid.go index 16e6490..f81f685 100644 --- a/mockid.go +++ b/mockid.go @@ -13,7 +13,6 @@ import ( "time" "git.coolaj86.com/coolaj86/go-mockid/mockid" - "git.coolaj86.com/coolaj86/go-mockid/xkeypairs" "git.rootprojects.org/root/keypairs" _ "github.com/joho/godotenv/autoload" @@ -92,7 +91,7 @@ func main() { }() // TODO privB := keypairs.MarshalJWKPrivateKey(privkey) - privB := xkeypairs.MarshalJWKPrivateKey(privkey) + privB := keypairs.MarshalJWKPrivateKey(privkey) fmt.Printf("Private Key:\n\t%s\n", string(privB)) pubB := keypairs.MarshalJWKPublicKey(keypairs.NewPublicKey(privkey.Public())) fmt.Printf("Public Key:\n\t%s\n", string(pubB)) diff --git a/mockid/api/common.go b/mockid/api/common.go index c2ca5ef..be19c61 100644 --- a/mockid/api/common.go +++ b/mockid/api/common.go @@ -13,6 +13,7 @@ import ( "net/http" "git.coolaj86.com/coolaj86/go-mockid/xkeypairs" + "git.rootprojects.org/root/keypairs" ) /* @@ -47,8 +48,8 @@ func getOpts(r *http.Request) (*xkeypairs.KeyOptions, error) { Key: key, } - opts.Claims, _ = tok["claims"].(xkeypairs.Object) - opts.Header, _ = tok["header"].(xkeypairs.Object) + opts.Claims, _ = tok["claims"].(keypairs.Object) + opts.Header, _ = tok["header"].(keypairs.Object) var n int if 0 != seed { diff --git a/mockid/api/generate.go b/mockid/api/generate.go index 3f36fb5..7d545ba 100644 --- a/mockid/api/generate.go +++ b/mockid/api/generate.go @@ -45,7 +45,7 @@ func GeneratePrivateJWK(w http.ResponseWriter, r *http.Request) { privkey := xkeypairs.GenPrivKey(opts) - jwk := xkeypairs.MarshalJWKPrivateKey(privkey) + jwk := keypairs.MarshalJWKPrivateKey(privkey) w.Write(append(jwk, '\n')) } @@ -68,7 +68,7 @@ func GeneratePublicDER(w http.ResponseWriter, r *http.Request) { return } - b, _ := xkeypairs.MarshalDERPublicKey(privkey.Public()) + b, _ := keypairs.MarshalDERPublicKey(privkey.Public()) w.Write(b) } @@ -88,7 +88,7 @@ func GeneratePrivateDER(w http.ResponseWriter, r *http.Request) { privkey := xkeypairs.GenPrivKey(opts) - der, _ := xkeypairs.MarshalDERPrivateKey(privkey) + der, _ := keypairs.MarshalDERPrivateKey(privkey) w.Write(der) } @@ -111,7 +111,7 @@ func GeneratePublicPEM(w http.ResponseWriter, r *http.Request) { return } - b, _ := xkeypairs.MarshalPEMPublicKey(privkey.Public()) + b, _ := keypairs.MarshalPEMPublicKey(privkey.Public()) w.Write(b) } @@ -131,7 +131,7 @@ func GeneratePrivatePEM(w http.ResponseWriter, r *http.Request) { privkey := xkeypairs.GenPrivKey(opts) - privpem, _ := xkeypairs.MarshalPEMPrivateKey(privkey) + privpem, _ := keypairs.MarshalPEMPrivateKey(privkey) w.Write(privpem) } diff --git a/mockid/api/sign.go b/mockid/api/sign.go index 36753bf..0050b44 100644 --- a/mockid/api/sign.go +++ b/mockid/api/sign.go @@ -4,7 +4,7 @@ import ( "encoding/json" "net/http" - "git.coolaj86.com/coolaj86/go-mockid/xkeypairs" + "git.rootprojects.org/root/keypairs" ) // SignJWS will create an uncompressed JWT with the given payload @@ -40,7 +40,7 @@ func sign(w http.ResponseWriter, r *http.Request, jwt bool) { header["_seed"] = opts.Seed } - jws, err := xkeypairs.SignClaims(privkey, header, opts.Claims) + jws, err := keypairs.SignClaims(privkey, header, opts.Claims) if nil != err { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -48,7 +48,7 @@ func sign(w http.ResponseWriter, r *http.Request, jwt bool) { var b []byte if jwt { - s := xkeypairs.JWSToJWT(jws) + s := keypairs.JWSToJWT(jws) w.Write(append([]byte(s), '\n')) return } diff --git a/mockid/api/verify.go b/mockid/api/verify.go index 61411b1..30f73a2 100644 --- a/mockid/api/verify.go +++ b/mockid/api/verify.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "git.coolaj86.com/coolaj86/go-mockid/xkeypairs" + "git.rootprojects.org/root/keypairs" ) // Verify will verify both JWT and uncompressed JWS @@ -19,7 +19,7 @@ func Verify(w http.ResponseWriter, r *http.Request) { return } - jws := &xkeypairs.JWS{} + jws := &keypairs.JWS{} authzParts := strings.Split(r.Header.Get("Authorization"), " ") lenAuthz := len(authzParts) @@ -75,16 +75,12 @@ func Verify(w http.ResponseWriter, r *http.Request) { jws.Claims["exp"] = float64(time.Now().Add(5 * time.Minute).Unix()) } - ok, err := xkeypairs.VerifyClaims(nil, jws) - if nil != err { - log.Printf("jws verify error: %s", err) + errs := keypairs.VerifyClaims(nil, jws) + if 0 == len(errs) { + log.Printf("jws verify error: %s", errs) http.Error(w, "Bad Request: could not verify JWS claims", http.StatusBadRequest) return } - if !ok { - http.Error(w, "Bad Request: invalid JWS signature", http.StatusBadRequest) - return - } b := []byte(`{"success":true}`) w.Write(append(b, '\n')) diff --git a/mockid/route.go b/mockid/route.go index 86204f4..411d64a 100644 --- a/mockid/route.go +++ b/mockid/route.go @@ -66,11 +66,13 @@ type OTPResponse struct { HTTPResponse } +// Contact represents a map between an identifier and some users type Contact struct { Email string `json:"email"` Subjects []string `json:"subjects"` } +// Subject represents a map between a user and some identifiers type Subject struct { Subject string `json:"subject"` Emails map[string]time.Time `json:"emails"` @@ -109,7 +111,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { if nil != err { signingKey = xkeypairs.GenPrivKey(&xkeypairs.KeyOptions{}) _ = os.MkdirAll(jwksPrefix+"/private", 0750) - b := xkeypairs.MarshalJWKPrivateKey(signingKey) + b := keypairs.MarshalJWKPrivateKey(signingKey) if err := ioutil.WriteFile(privKeyJWKPath, b, 0600); nil != err { panic(err) } @@ -320,10 +322,10 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { uuid, _ := uuid.NewRandom() nonce, _ := uuid.MarshalBinary() baseURL := getBaseURL(r) - tok, err := xkeypairs.SignClaims( + tok, err := keypairs.SignClaims( signingKey, - xkeypairs.Object{}, - xkeypairs.Object{ + keypairs.Object{}, + keypairs.Object{ "sub": sub, "iss": baseURL + "/", "jti": base64.RawURLEncoding.EncodeToString(nonce), @@ -336,7 +338,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { fmt.Fprintf(w, "%s", err) return } - otp.AccessToken = xkeypairs.JWSToJWT(tok) + otp.AccessToken = keypairs.JWSToJWT(tok) b, _ := json.Marshal(&OTPResponse{ HTTPResponse: HTTPResponse{Success: true}, OTP: *otp, @@ -461,7 +463,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { http.HandleFunc("/api/new-account", func(w http.ResponseWriter, r *http.Request) { myURL := getBaseURL(r) + r.URL.Path - jws := &xkeypairs.JWS{} + jws := &keypairs.JWS{} decoder := json.NewDecoder(r.Body) if err := decoder.Decode(jws); nil != err { @@ -504,11 +506,8 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { return } - ok, err := xkeypairs.VerifyClaims(nil, jws) - if nil != err || !ok { - if nil != err { - log.Printf("jws verify error: %s", err) - } + errs := keypairs.VerifyClaims(nil, jws) + if 0 != len(errs) { http.Error(w, "Bad Request", http.StatusBadRequest) fmt.Fprintf(w, `{"error":"could not verify JWS claims"}`+"\n") return @@ -530,7 +529,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { ) if nil != err { http.Error(w, "Bad Request", http.StatusBadRequest) - msg, _ := json.Marshal(err.Error()) + msg, _ := json.Marshal(err) fmt.Fprintf(w, `{"error":%s}`+"\n", msg) return } @@ -684,7 +683,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { http.HandleFunc("/key.jwk.json", func(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.Method, r.URL.Path) - jwk := string(xkeypairs.MarshalJWKPrivateKey(privkey)) + jwk := string(keypairs.MarshalJWKPrivateKey(privkey)) jwk = strings.Replace(jwk, `{"`, `{ "`, 1) jwk = strings.Replace(jwk, `",`, `", `, -1) jwk = jwk[0 : len(jwk)-1] @@ -816,6 +815,7 @@ func verifyToken(token string) (*InspectableToken, error) { return inspected, nil } +// OTP is the one-time password for auth type OTP struct { //Attempts int `json:"attempts"` CreatedAt time.Time `json:"created_at"` diff --git a/xkeypairs/jose.go b/oldxkeypairs/jose.go similarity index 100% rename from xkeypairs/jose.go rename to oldxkeypairs/jose.go diff --git a/xkeypairs/jwk.go b/oldxkeypairs/jwk.go similarity index 100% rename from xkeypairs/jwk.go rename to oldxkeypairs/jwk.go diff --git a/xkeypairs/marshal.go b/oldxkeypairs/marshal.go similarity index 100% rename from xkeypairs/marshal.go rename to oldxkeypairs/marshal.go diff --git a/xkeypairs/sign.go b/oldxkeypairs/sign.go similarity index 100% rename from xkeypairs/sign.go rename to oldxkeypairs/sign.go diff --git a/xkeypairs/verify.go b/oldxkeypairs/verify.go similarity index 100% rename from xkeypairs/verify.go rename to oldxkeypairs/verify.go diff --git a/xkeypairs/generate.go b/xkeypairs/generate.go index 73a59c6..b150179 100644 --- a/xkeypairs/generate.go +++ b/xkeypairs/generate.go @@ -3,22 +3,30 @@ package xkeypairs import ( "crypto/ecdsa" "crypto/elliptic" + "crypto/rand" "crypto/rsa" "io" "log" - "math/rand" + mathrand "math/rand" "git.rootprojects.org/root/keypairs" ) +const maxRetry = 16 + +// RandomReader may be overwritten for testing +var RandomReader io.Reader = rand.Reader + +//var RandomReader = rand.Reader + // KeyOptions are the things that we may need to know about a request to fulfill it properly type KeyOptions struct { - Key string `json:"key"` - KeyType string `json:"kty"` - Seed int64 `json:"-"` - SeedStr string `json:"seed"` - Claims Object `json:"claims"` - Header Object `json:"header"` + Key string `json:"key"` + KeyType string `json:"kty"` + Seed int64 `json:"-"` + SeedStr string `json:"seed"` + Claims keypairs.Object `json:"claims"` + Header keypairs.Object `json:"header"` } // this shananigans is only for testing and debug API stuff @@ -26,7 +34,7 @@ func (o *KeyOptions) MyFooNextReader() io.Reader { if 0 == o.Seed { return RandomReader } - return rand.New(rand.NewSource(o.Seed)) + return mathrand.New(mathrand.NewSource(o.Seed)) } // GenPrivKey generates a 256-bit entropy RSA or ECDSA private key