Compare commits
	
		
			No commits in common. "3f7513364a5bd7cdce0fa9766850f1ec9c0bc606" and "6a22bfecc40cdba566d2e0619110dc14a8aaf8a0" have entirely different histories.
		
	
	
		
			3f7513364a
			...
			6a22bfecc4
		
	
		
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ go 1.13 | |||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	git.rootprojects.org/root/hashcash v1.0.1 | 	git.rootprojects.org/root/hashcash v1.0.1 | ||||||
| 	git.rootprojects.org/root/keypairs v0.6.5 | 	git.rootprojects.org/root/keypairs v0.5.2 | ||||||
| 	github.com/google/uuid v1.1.1 | 	github.com/google/uuid v1.1.1 | ||||||
| 	github.com/joho/godotenv v1.3.0 | 	github.com/joho/godotenv v1.3.0 | ||||||
| 	github.com/mailgun/mailgun-go/v3 v3.6.4 | 	github.com/mailgun/mailgun-go/v3 v3.6.4 | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | |||||||
| git.rootprojects.org/root/hashcash v1.0.1 h1:PkzwZu4CR5q/hwAntJdvcmNhmP0ONhetMo7rYhIZhZ0= | git.rootprojects.org/root/hashcash v1.0.1 h1:PkzwZu4CR5q/hwAntJdvcmNhmP0ONhetMo7rYhIZhZ0= | ||||||
| git.rootprojects.org/root/hashcash v1.0.1/go.mod h1:HdoULUe94o1NVMES5K6aP3p8QGQiIia73F1HNZ1+FkQ= | git.rootprojects.org/root/hashcash v1.0.1/go.mod h1:HdoULUe94o1NVMES5K6aP3p8QGQiIia73F1HNZ1+FkQ= | ||||||
| git.rootprojects.org/root/keypairs v0.6.5 h1:sdRAQD/O/JBS8+ZxUewXnY+cjQVDNH3TmcS+KtANZqA= | git.rootprojects.org/root/keypairs v0.5.2 h1:jr+drUUm/REaCDJTl5gT3kF2PwlXygcLsBZlqoKTZZw= | ||||||
| git.rootprojects.org/root/keypairs v0.6.5/go.mod h1:WGI8PadOp+4LjUuI+wNlSwcJwFtY8L9XuNjuO3213HA= | git.rootprojects.org/root/keypairs v0.5.2/go.mod h1:WGI8PadOp+4LjUuI+wNlSwcJwFtY8L9XuNjuO3213HA= | ||||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
| github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= | github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"git.coolaj86.com/coolaj86/go-mockid/mockid" | 	"git.coolaj86.com/coolaj86/go-mockid/mockid" | ||||||
|  | 	"git.coolaj86.com/coolaj86/go-mockid/xkeypairs" | ||||||
| 	"git.rootprojects.org/root/keypairs" | 	"git.rootprojects.org/root/keypairs" | ||||||
| 
 | 
 | ||||||
| 	_ "github.com/joho/godotenv/autoload" | 	_ "github.com/joho/godotenv/autoload" | ||||||
| @ -91,7 +92,7 @@ func main() { | |||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
| 	// TODO privB := keypairs.MarshalJWKPrivateKey(privkey) | 	// TODO privB := keypairs.MarshalJWKPrivateKey(privkey) | ||||||
| 	privB := keypairs.MarshalJWKPrivateKey(privkey) | 	privB := xkeypairs.MarshalJWKPrivateKey(privkey) | ||||||
| 	fmt.Printf("Private Key:\n\t%s\n", string(privB)) | 	fmt.Printf("Private Key:\n\t%s\n", string(privB)) | ||||||
| 	pubB := keypairs.MarshalJWKPublicKey(keypairs.NewPublicKey(privkey.Public())) | 	pubB := keypairs.MarshalJWKPublicKey(keypairs.NewPublicKey(privkey.Public())) | ||||||
| 	fmt.Printf("Public Key:\n\t%s\n", string(pubB)) | 	fmt.Printf("Public Key:\n\t%s\n", string(pubB)) | ||||||
|  | |||||||
| @ -13,7 +13,6 @@ import ( | |||||||
| 	"net/http" | 	"net/http" | ||||||
| 
 | 
 | ||||||
| 	"git.coolaj86.com/coolaj86/go-mockid/xkeypairs" | 	"git.coolaj86.com/coolaj86/go-mockid/xkeypairs" | ||||||
| 	"git.rootprojects.org/root/keypairs" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
| @ -48,8 +47,8 @@ func getOpts(r *http.Request) (*xkeypairs.KeyOptions, error) { | |||||||
| 		Key:  key, | 		Key:  key, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	opts.Claims, _ = tok["claims"].(keypairs.Object) | 	opts.Claims, _ = tok["claims"].(xkeypairs.Object) | ||||||
| 	opts.Header, _ = tok["header"].(keypairs.Object) | 	opts.Header, _ = tok["header"].(xkeypairs.Object) | ||||||
| 
 | 
 | ||||||
| 	var n int | 	var n int | ||||||
| 	if 0 != seed { | 	if 0 != seed { | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ func GeneratePrivateJWK(w http.ResponseWriter, r *http.Request) { | |||||||
| 
 | 
 | ||||||
| 	privkey := xkeypairs.GenPrivKey(opts) | 	privkey := xkeypairs.GenPrivKey(opts) | ||||||
| 
 | 
 | ||||||
| 	jwk := keypairs.MarshalJWKPrivateKey(privkey) | 	jwk := xkeypairs.MarshalJWKPrivateKey(privkey) | ||||||
| 	w.Write(append(jwk, '\n')) | 	w.Write(append(jwk, '\n')) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -68,7 +68,7 @@ func GeneratePublicDER(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	b, _ := keypairs.MarshalDERPublicKey(privkey.Public()) | 	b, _ := xkeypairs.MarshalDERPublicKey(privkey.Public()) | ||||||
| 
 | 
 | ||||||
| 	w.Write(b) | 	w.Write(b) | ||||||
| } | } | ||||||
| @ -88,7 +88,7 @@ func GeneratePrivateDER(w http.ResponseWriter, r *http.Request) { | |||||||
| 
 | 
 | ||||||
| 	privkey := xkeypairs.GenPrivKey(opts) | 	privkey := xkeypairs.GenPrivKey(opts) | ||||||
| 
 | 
 | ||||||
| 	der, _ := keypairs.MarshalDERPrivateKey(privkey) | 	der, _ := xkeypairs.MarshalDERPrivateKey(privkey) | ||||||
| 	w.Write(der) | 	w.Write(der) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -111,7 +111,7 @@ func GeneratePublicPEM(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	b, _ := keypairs.MarshalPEMPublicKey(privkey.Public()) | 	b, _ := xkeypairs.MarshalPEMPublicKey(privkey.Public()) | ||||||
| 
 | 
 | ||||||
| 	w.Write(b) | 	w.Write(b) | ||||||
| } | } | ||||||
| @ -131,7 +131,7 @@ func GeneratePrivatePEM(w http.ResponseWriter, r *http.Request) { | |||||||
| 
 | 
 | ||||||
| 	privkey := xkeypairs.GenPrivKey(opts) | 	privkey := xkeypairs.GenPrivKey(opts) | ||||||
| 
 | 
 | ||||||
| 	privpem, _ := keypairs.MarshalPEMPrivateKey(privkey) | 	privpem, _ := xkeypairs.MarshalPEMPrivateKey(privkey) | ||||||
| 	w.Write(privpem) | 	w.Write(privpem) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 
 | 
 | ||||||
| 	"git.rootprojects.org/root/keypairs" | 	"git.coolaj86.com/coolaj86/go-mockid/xkeypairs" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // SignJWS will create an uncompressed JWT with the given payload | // 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 | 		header["_seed"] = opts.Seed | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	jws, err := keypairs.SignClaims(privkey, header, opts.Claims) | 	jws, err := xkeypairs.SignClaims(privkey, header, opts.Claims) | ||||||
| 	if nil != err { | 	if nil != err { | ||||||
| 		http.Error(w, err.Error(), http.StatusBadRequest) | 		http.Error(w, err.Error(), http.StatusBadRequest) | ||||||
| 		return | 		return | ||||||
| @ -48,7 +48,7 @@ func sign(w http.ResponseWriter, r *http.Request, jwt bool) { | |||||||
| 
 | 
 | ||||||
| 	var b []byte | 	var b []byte | ||||||
| 	if jwt { | 	if jwt { | ||||||
| 		s := keypairs.JWSToJWT(jws) | 		s := xkeypairs.JWSToJWT(jws) | ||||||
| 		w.Write(append([]byte(s), '\n')) | 		w.Write(append([]byte(s), '\n')) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"git.rootprojects.org/root/keypairs" | 	"git.coolaj86.com/coolaj86/go-mockid/xkeypairs" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Verify will verify both JWT and uncompressed JWS | // Verify will verify both JWT and uncompressed JWS | ||||||
| @ -19,7 +19,7 @@ func Verify(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	jws := &keypairs.JWS{} | 	jws := &xkeypairs.JWS{} | ||||||
| 
 | 
 | ||||||
| 	authzParts := strings.Split(r.Header.Get("Authorization"), " ") | 	authzParts := strings.Split(r.Header.Get("Authorization"), " ") | ||||||
| 	lenAuthz := len(authzParts) | 	lenAuthz := len(authzParts) | ||||||
| @ -75,12 +75,16 @@ func Verify(w http.ResponseWriter, r *http.Request) { | |||||||
| 		jws.Claims["exp"] = float64(time.Now().Add(5 * time.Minute).Unix()) | 		jws.Claims["exp"] = float64(time.Now().Add(5 * time.Minute).Unix()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	errs := keypairs.VerifyClaims(nil, jws) | 	ok, err := xkeypairs.VerifyClaims(nil, jws) | ||||||
| 	if 0 == len(errs) { | 	if nil != err { | ||||||
| 		log.Printf("jws verify error: %s", errs) | 		log.Printf("jws verify error: %s", err) | ||||||
| 		http.Error(w, "Bad Request: could not verify JWS claims", http.StatusBadRequest) | 		http.Error(w, "Bad Request: could not verify JWS claims", http.StatusBadRequest) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 	if !ok { | ||||||
|  | 		http.Error(w, "Bad Request: invalid JWS signature", http.StatusBadRequest) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	b := []byte(`{"success":true}`) | 	b := []byte(`{"success":true}`) | ||||||
| 	w.Write(append(b, '\n')) | 	w.Write(append(b, '\n')) | ||||||
|  | |||||||
| @ -66,13 +66,11 @@ type OTPResponse struct { | |||||||
| 	HTTPResponse | 	HTTPResponse | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Contact represents a map between an identifier and some users |  | ||||||
| type Contact struct { | type Contact struct { | ||||||
| 	Email    string   `json:"email"` | 	Email    string   `json:"email"` | ||||||
| 	Subjects []string `json:"subjects"` | 	Subjects []string `json:"subjects"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Subject represents a map between a user and some identifiers |  | ||||||
| type Subject struct { | type Subject struct { | ||||||
| 	Subject string               `json:"subject"` | 	Subject string               `json:"subject"` | ||||||
| 	Emails  map[string]time.Time `json:"emails"` | 	Emails  map[string]time.Time `json:"emails"` | ||||||
| @ -111,7 +109,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 	if nil != err { | 	if nil != err { | ||||||
| 		signingKey = xkeypairs.GenPrivKey(&xkeypairs.KeyOptions{}) | 		signingKey = xkeypairs.GenPrivKey(&xkeypairs.KeyOptions{}) | ||||||
| 		_ = os.MkdirAll(jwksPrefix+"/private", 0750) | 		_ = os.MkdirAll(jwksPrefix+"/private", 0750) | ||||||
| 		b := keypairs.MarshalJWKPrivateKey(signingKey) | 		b := xkeypairs.MarshalJWKPrivateKey(signingKey) | ||||||
| 		if err := ioutil.WriteFile(privKeyJWKPath, b, 0600); nil != err { | 		if err := ioutil.WriteFile(privKeyJWKPath, b, 0600); nil != err { | ||||||
| 			panic(err) | 			panic(err) | ||||||
| 		} | 		} | ||||||
| @ -322,10 +320,10 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 		uuid, _ := uuid.NewRandom() | 		uuid, _ := uuid.NewRandom() | ||||||
| 		nonce, _ := uuid.MarshalBinary() | 		nonce, _ := uuid.MarshalBinary() | ||||||
| 		baseURL := getBaseURL(r) | 		baseURL := getBaseURL(r) | ||||||
| 		tok, err := keypairs.SignClaims( | 		tok, err := xkeypairs.SignClaims( | ||||||
| 			signingKey, | 			signingKey, | ||||||
| 			keypairs.Object{}, | 			xkeypairs.Object{}, | ||||||
| 			keypairs.Object{ | 			xkeypairs.Object{ | ||||||
| 				"sub": sub, | 				"sub": sub, | ||||||
| 				"iss": baseURL + "/", | 				"iss": baseURL + "/", | ||||||
| 				"jti": base64.RawURLEncoding.EncodeToString(nonce), | 				"jti": base64.RawURLEncoding.EncodeToString(nonce), | ||||||
| @ -338,7 +336,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 			fmt.Fprintf(w, "%s", err) | 			fmt.Fprintf(w, "%s", err) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		otp.AccessToken = keypairs.JWSToJWT(tok) | 		otp.AccessToken = xkeypairs.JWSToJWT(tok) | ||||||
| 		b, _ := json.Marshal(&OTPResponse{ | 		b, _ := json.Marshal(&OTPResponse{ | ||||||
| 			HTTPResponse: HTTPResponse{Success: true}, | 			HTTPResponse: HTTPResponse{Success: true}, | ||||||
| 			OTP:          *otp, | 			OTP:          *otp, | ||||||
| @ -463,7 +461,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 	http.HandleFunc("/api/new-account", func(w http.ResponseWriter, r *http.Request) { | 	http.HandleFunc("/api/new-account", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		myURL := getBaseURL(r) + r.URL.Path | 		myURL := getBaseURL(r) + r.URL.Path | ||||||
| 
 | 
 | ||||||
| 		jws := &keypairs.JWS{} | 		jws := &xkeypairs.JWS{} | ||||||
| 
 | 
 | ||||||
| 		decoder := json.NewDecoder(r.Body) | 		decoder := json.NewDecoder(r.Body) | ||||||
| 		if err := decoder.Decode(jws); nil != err { | 		if err := decoder.Decode(jws); nil != err { | ||||||
| @ -506,8 +504,11 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		errs := keypairs.VerifyClaims(nil, jws) | 		ok, err := xkeypairs.VerifyClaims(nil, jws) | ||||||
| 		if 0 != len(errs) { | 		if nil != err || !ok { | ||||||
|  | 			if nil != err { | ||||||
|  | 				log.Printf("jws verify error: %s", err) | ||||||
|  | 			} | ||||||
| 			http.Error(w, "Bad Request", http.StatusBadRequest) | 			http.Error(w, "Bad Request", http.StatusBadRequest) | ||||||
| 			fmt.Fprintf(w, `{"error":"could not verify JWS claims"}`+"\n") | 			fmt.Fprintf(w, `{"error":"could not verify JWS claims"}`+"\n") | ||||||
| 			return | 			return | ||||||
| @ -529,7 +530,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 		) | 		) | ||||||
| 		if nil != err { | 		if nil != err { | ||||||
| 			http.Error(w, "Bad Request", http.StatusBadRequest) | 			http.Error(w, "Bad Request", http.StatusBadRequest) | ||||||
| 			msg, _ := json.Marshal(err) | 			msg, _ := json.Marshal(err.Error()) | ||||||
| 			fmt.Fprintf(w, `{"error":%s}`+"\n", msg) | 			fmt.Fprintf(w, `{"error":%s}`+"\n", msg) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| @ -683,7 +684,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { | |||||||
| 
 | 
 | ||||||
| 	http.HandleFunc("/key.jwk.json", func(w http.ResponseWriter, r *http.Request) { | 	http.HandleFunc("/key.jwk.json", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		log.Printf("%s %s", r.Method, r.URL.Path) | 		log.Printf("%s %s", r.Method, r.URL.Path) | ||||||
| 		jwk := string(keypairs.MarshalJWKPrivateKey(privkey)) | 		jwk := string(xkeypairs.MarshalJWKPrivateKey(privkey)) | ||||||
| 		jwk = strings.Replace(jwk, `{"`, `{ "`, 1) | 		jwk = strings.Replace(jwk, `{"`, `{ "`, 1) | ||||||
| 		jwk = strings.Replace(jwk, `",`, `", `, -1) | 		jwk = strings.Replace(jwk, `",`, `", `, -1) | ||||||
| 		jwk = jwk[0 : len(jwk)-1] | 		jwk = jwk[0 : len(jwk)-1] | ||||||
| @ -815,7 +816,6 @@ func verifyToken(token string) (*InspectableToken, error) { | |||||||
| 	return inspected, nil | 	return inspected, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // OTP is the one-time password for auth |  | ||||||
| type OTP struct { | type OTP struct { | ||||||
| 	//Attempts    int       `json:"attempts"` | 	//Attempts    int       `json:"attempts"` | ||||||
| 	CreatedAt   time.Time `json:"created_at"` | 	CreatedAt   time.Time `json:"created_at"` | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								vendor/git.rootprojects.org/root/keypairs/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/git.rootprojects.org/root/keypairs/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,5 +0,0 @@ | |||||||
| /keypairs |  | ||||||
| /dist/ |  | ||||||
| 
 |  | ||||||
| .DS_Store |  | ||||||
| .*.sw* |  | ||||||
							
								
								
									
										41
									
								
								vendor/git.rootprojects.org/root/keypairs/.goreleaser.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/git.rootprojects.org/root/keypairs/.goreleaser.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,41 +0,0 @@ | |||||||
| # This is an example goreleaser.yaml file with some sane defaults. |  | ||||||
| # Make sure to check the documentation at http://goreleaser.com |  | ||||||
| before: |  | ||||||
|   hooks: |  | ||||||
|     - go generate ./... |  | ||||||
| builds: |  | ||||||
|   - id: keypairs |  | ||||||
|     main: ./cmd/keypairs/keypairs.go |  | ||||||
|     env: |  | ||||||
|       - CGO_ENABLED=0 |  | ||||||
|     flags: |  | ||||||
|       - -mod=vendor |  | ||||||
|     goos: |  | ||||||
|       - linux |  | ||||||
|       - windows |  | ||||||
|       - darwin |  | ||||||
|       - freebsd |  | ||||||
|     goarch: |  | ||||||
|       - amd64 |  | ||||||
|       - arm |  | ||||||
|       - arm64 |  | ||||||
| archives: |  | ||||||
|   - replacements: |  | ||||||
|       386: i386 |  | ||||||
|       amd64: x86-64 |  | ||||||
|       arm64: aarch64 |  | ||||||
|     format_overrides: |  | ||||||
|       - goos: windows |  | ||||||
|         format: zip |  | ||||||
| env_files: |  | ||||||
|   github_token: ~/.config/goreleaser/github_token.txt |  | ||||||
| checksum: |  | ||||||
|   name_template: 'checksums.txt' |  | ||||||
| snapshot: |  | ||||||
|   name_template: "{{ .Tag }}-next" |  | ||||||
| changelog: |  | ||||||
|   sort: asc |  | ||||||
|   filters: |  | ||||||
|     exclude: |  | ||||||
|       - '^docs:' |  | ||||||
|       - '^test:' |  | ||||||
							
								
								
									
										1
									
								
								vendor/git.rootprojects.org/root/keypairs/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/git.rootprojects.org/root/keypairs/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1 +0,0 @@ | |||||||
| AJ ONeal <aj@therootcompany.com> (https://therootcompany.com) |  | ||||||
							
								
								
									
										10
									
								
								vendor/git.rootprojects.org/root/keypairs/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/git.rootprojects.org/root/keypairs/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| # [keypairs](https://git.rootprojects.org/root/keypairs) | # go-keypairs | ||||||
| 
 | 
 | ||||||
| JSON Web Key (JWK) support and type safety lightly placed over top of Go's `crypto/ecdsa` and `crypto/rsa` | JSON Web Key (JWK) support and type safety lightly placed over top of Go's `crypto/ecdsa` and `crypto/rsa` | ||||||
| 
 | 
 | ||||||
| @ -14,9 +14,9 @@ jwk, err := keypairs.MarshalJWKPublicKey(pub, time.Now().Add(2 * time.Day)) | |||||||
| kid, err := keypairs.ThumbprintPublicKey(pub) | kid, err := keypairs.ThumbprintPublicKey(pub) | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| # GoDoc API Documentation | # API Documentation | ||||||
| 
 | 
 | ||||||
| See <https://pkg.go.dev/git.rootprojects.org/root/keypairs> | See <https://godoc.org/github.com/big-squid/go-keypairs> | ||||||
| 
 | 
 | ||||||
| # Philosophy | # Philosophy | ||||||
| 
 | 
 | ||||||
| @ -56,8 +56,8 @@ between the ASN.1, x509, PEM, and JWK formats. | |||||||
| 
 | 
 | ||||||
| # LICENSE | # LICENSE | ||||||
| 
 | 
 | ||||||
| Copyright (c) 2020-present AJ ONeal \ | Copyright (c) 2020-present AJ ONeal | ||||||
| Copyright (c) 2018-2019 Big Squid, Inc. | Copyright (c) 2018-2019 Big Squid, Inc. | ||||||
| 
 | 
 | ||||||
| This work is licensed under the terms of the MIT license. \ | This work is licensed under the terms of the MIT license. | ||||||
| For a copy, see <https://opensource.org/licenses/MIT>. | For a copy, see <https://opensource.org/licenses/MIT>. | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								vendor/git.rootprojects.org/root/keypairs/cli_test.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/git.rootprojects.org/root/keypairs/cli_test.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,19 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
| set -u |  | ||||||
| 
 |  | ||||||
| go build -mod=vendor cmd/keypairs/*.go |  | ||||||
| ./keypairs gen > testkey.jwk.json 2> testpub.jwk.json |  | ||||||
| 
 |  | ||||||
| ./keypairs sign --exp 1h ./testkey.jwk.json '{"foo":"bar"}' > testjwt.txt 2> testjws.json |  | ||||||
| 
 |  | ||||||
| echo "" |  | ||||||
| echo "Should pass:" |  | ||||||
| ./keypairs verify ./testpub.jwk.json testjwt.txt > /dev/null |  | ||||||
| ./keypairs verify ./testpub.jwk.json "$(cat testjwt.txt)" > /dev/null |  | ||||||
| ./keypairs verify ./testpub.jwk.json testjws.json > /dev/null |  | ||||||
| ./keypairs verify ./testpub.jwk.json "$(cat testjws.json)" > /dev/null |  | ||||||
| 
 |  | ||||||
| echo "" |  | ||||||
| echo "Should fail:" |  | ||||||
| ./keypairs sign --exp -1m ./testkey.jwk.json '{"bar":"foo"}' > errjwt.txt 2> errjws.json |  | ||||||
| ./keypairs verify ./testpub.jwk.json errjwt.txt > /dev/null |  | ||||||
							
								
								
									
										69
									
								
								vendor/git.rootprojects.org/root/keypairs/generate.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								vendor/git.rootprojects.org/root/keypairs/generate.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,69 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"crypto/ecdsa" |  | ||||||
| 	"crypto/elliptic" |  | ||||||
| 	"crypto/rand" |  | ||||||
| 	"crypto/rsa" |  | ||||||
| 	"io" |  | ||||||
| 	mathrand "math/rand" |  | ||||||
| 	"time" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var randReader io.Reader = rand.Reader |  | ||||||
| var allowMocking = false |  | ||||||
| 
 |  | ||||||
| // 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"` |  | ||||||
| 	mockSeed int64  //`json:"-"` |  | ||||||
| 	//SeedStr string `json:"seed"` |  | ||||||
| 	//Claims  Object `json:"claims"` |  | ||||||
| 	//Header  Object `json:"header"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (o *keyOptions) nextReader() io.Reader { |  | ||||||
| 	if allowMocking { |  | ||||||
| 		return o.maybeMockReader() |  | ||||||
| 	} |  | ||||||
| 	return randReader |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // NewDefaultPrivateKey generates a key with reasonable strength. |  | ||||||
| // Today that means a 256-bit equivalent - either RSA 2048 or EC P-256. |  | ||||||
| func NewDefaultPrivateKey() PrivateKey { |  | ||||||
| 	// insecure random is okay here, |  | ||||||
| 	// it's just used for a coin toss |  | ||||||
| 	mathrand.Seed(time.Now().UnixNano()) |  | ||||||
| 	coin := mathrand.Int() |  | ||||||
| 
 |  | ||||||
| 	// the idea here is that we want to make |  | ||||||
| 	// it dead simple to support RSA and EC |  | ||||||
| 	// so it shouldn't matter which is used |  | ||||||
| 	if 0 == coin%2 { |  | ||||||
| 		return newPrivateKey(&keyOptions{ |  | ||||||
| 			KeyType: "RSA", |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| 	return newPrivateKey(&keyOptions{ |  | ||||||
| 		KeyType: "EC", |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // newPrivateKey generates a 256-bit entropy RSA or ECDSA private key |  | ||||||
| func newPrivateKey(opts *keyOptions) PrivateKey { |  | ||||||
| 	var privkey PrivateKey |  | ||||||
| 
 |  | ||||||
| 	if "RSA" == opts.KeyType { |  | ||||||
| 		keylen := 2048 |  | ||||||
| 		privkey, _ = rsa.GenerateKey(opts.nextReader(), keylen) |  | ||||||
| 		if allowMocking { |  | ||||||
| 			privkey = maybeDerandomizeMockKey(privkey, keylen, opts) |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		// TODO: EC keys may also suffer the same random problems in the future |  | ||||||
| 		privkey, _ = ecdsa.GenerateKey(elliptic.P256(), opts.nextReader()) |  | ||||||
| 	} |  | ||||||
| 	return privkey |  | ||||||
| } |  | ||||||
							
								
								
									
										69
									
								
								vendor/git.rootprojects.org/root/keypairs/jwk.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								vendor/git.rootprojects.org/root/keypairs/jwk.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,69 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // JWK abstracts EC and RSA keys |  | ||||||
| type JWK interface { |  | ||||||
| 	marshalJWK() ([]byte, error) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ECJWK is the EC variant |  | ||||||
| type ECJWK struct { |  | ||||||
| 	KeyID string   `json:"kid,omitempty"` |  | ||||||
| 	Curve string   `json:"crv"` |  | ||||||
| 	X     string   `json:"x"` |  | ||||||
| 	Y     string   `json:"y"` |  | ||||||
| 	Use   []string `json:"use,omitempty"` |  | ||||||
| 	Seed  string   `json:"_seed,omitempty"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (k *ECJWK) marshalJWK() ([]byte, error) { |  | ||||||
| 	return []byte(fmt.Sprintf(`{"crv":%q,"kty":"EC","x":%q,"y":%q}`, k.Curve, k.X, k.Y)), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RSAJWK is the RSA variant |  | ||||||
| type RSAJWK struct { |  | ||||||
| 	KeyID string   `json:"kid,omitempty"` |  | ||||||
| 	Exp   string   `json:"e"` |  | ||||||
| 	N     string   `json:"n"` |  | ||||||
| 	Use   []string `json:"use,omitempty"` |  | ||||||
| 	Seed  string   `json:"_seed,omitempty"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (k *RSAJWK) marshalJWK() ([]byte, error) { |  | ||||||
| 	return []byte(fmt.Sprintf(`{"e":%q,"kty":"RSA","n":%q}`, k.Exp, k.N)), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| // ToPublicJWK exposes only the public parts |  | ||||||
| func ToPublicJWK(pubkey PublicKey) JWK { |  | ||||||
| 	switch k := pubkey.Key().(type) { |  | ||||||
| 	case *ecdsa.PublicKey: |  | ||||||
| 		return ECToPublicJWK(k) |  | ||||||
| 	case *rsa.PublicKey: |  | ||||||
| 		return RSAToPublicJWK(k) |  | ||||||
| 	default: |  | ||||||
| 		panic(errors.New("impossible key type")) |  | ||||||
| 		//return nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ECToPublicJWK will output the most minimal version of an EC JWK (no key id, no "use" flag, nada) |  | ||||||
| func ECToPublicJWK(k *ecdsa.PublicKey) *ECJWK { |  | ||||||
| 	return &ECJWK{ |  | ||||||
| 		Curve: k.Curve.Params().Name, |  | ||||||
| 		X:     base64.RawURLEncoding.EncodeToString(k.X.Bytes()), |  | ||||||
| 		Y:     base64.RawURLEncoding.EncodeToString(k.Y.Bytes()), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RSAToPublicJWK will output the most minimal version of an RSA JWK (no key id, no "use" flag, nada) |  | ||||||
| func RSAToPublicJWK(p *rsa.PublicKey) *RSAJWK { |  | ||||||
| 	return &RSAJWK{ |  | ||||||
| 		Exp: base64.RawURLEncoding.EncodeToString(big.NewInt(int64(p.E)).Bytes()), |  | ||||||
| 		N:   base64.RawURLEncoding.EncodeToString(p.N.Bytes()), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| */ |  | ||||||
							
								
								
									
										63
									
								
								vendor/git.rootprojects.org/root/keypairs/jws.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										63
									
								
								vendor/git.rootprojects.org/root/keypairs/jws.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,63 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"encoding/base64" |  | ||||||
| 	"encoding/json" |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"strings" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // JWS is a parsed JWT, representation as signable/verifiable and human-readable parts |  | ||||||
| type JWS struct { |  | ||||||
| 	Header    Object `json:"header"`    // JSON |  | ||||||
| 	Claims    Object `json:"claims"`    // JSON |  | ||||||
| 	Protected string `json:"protected"` // base64 |  | ||||||
| 	Payload   string `json:"payload"`   // base64 |  | ||||||
| 	Signature string `json:"signature"` // base64 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // JWSToJWT joins JWS parts into a JWT as {ProtectedHeader}.{SerializedPayload}.{Signature}. |  | ||||||
| func JWSToJWT(jwt *JWS) string { |  | ||||||
| 	return fmt.Sprintf( |  | ||||||
| 		"%s.%s.%s", |  | ||||||
| 		jwt.Protected, |  | ||||||
| 		jwt.Payload, |  | ||||||
| 		jwt.Signature, |  | ||||||
| 	) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // JWTToJWS splits the JWT into its JWS segments |  | ||||||
| func JWTToJWS(jwt string) (jws *JWS) { |  | ||||||
| 	jwt = strings.TrimSpace(jwt) |  | ||||||
| 	parts := strings.Split(jwt, ".") |  | ||||||
| 	if 3 != len(parts) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	return &JWS{ |  | ||||||
| 		Protected: parts[0], |  | ||||||
| 		Payload:   parts[1], |  | ||||||
| 		Signature: parts[2], |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // DecodeComponents decodes JWS Header and Claims |  | ||||||
| func (jws *JWS) DecodeComponents() error { |  | ||||||
| 	protected, err := base64.RawURLEncoding.DecodeString(jws.Protected) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return errors.New("invalid JWS header base64Url encoding") |  | ||||||
| 	} |  | ||||||
| 	if err := json.Unmarshal([]byte(protected), &jws.Header); nil != err { |  | ||||||
| 		return errors.New("invalid JWS header") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	payload, err := base64.RawURLEncoding.DecodeString(jws.Payload) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return errors.New("invalid JWS payload base64Url encoding") |  | ||||||
| 	} |  | ||||||
| 	if err := json.Unmarshal([]byte(payload), &jws.Claims); nil != err { |  | ||||||
| 		return errors.New("invalid JWS claims") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
							
								
								
									
										171
									
								
								vendor/git.rootprojects.org/root/keypairs/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										171
									
								
								vendor/git.rootprojects.org/root/keypairs/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,171 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"crypto" |  | ||||||
| 	"crypto/ecdsa" |  | ||||||
| 	"crypto/rsa" |  | ||||||
| 	"crypto/x509" |  | ||||||
| 	"encoding/base64" |  | ||||||
| 	"encoding/pem" |  | ||||||
| 	"fmt" |  | ||||||
| 	"log" |  | ||||||
| 	"math/big" |  | ||||||
| 	mathrand "math/rand" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // MarshalPEMPublicKey outputs the given public key as JWK |  | ||||||
| func MarshalPEMPublicKey(pubkey crypto.PublicKey) ([]byte, error) { |  | ||||||
| 	block, err := marshalDERPublicKey(pubkey) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return pem.EncodeToMemory(block), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MarshalDERPublicKey outputs the given public key as JWK |  | ||||||
| func MarshalDERPublicKey(pubkey crypto.PublicKey) ([]byte, error) { |  | ||||||
| 	block, err := marshalDERPublicKey(pubkey) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return block.Bytes, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // marshalDERPublicKey outputs the given public key as JWK |  | ||||||
| func marshalDERPublicKey(pubkey crypto.PublicKey) (*pem.Block, error) { |  | ||||||
| 
 |  | ||||||
| 	var der []byte |  | ||||||
| 	var typ string |  | ||||||
| 	var err error |  | ||||||
| 	switch k := pubkey.(type) { |  | ||||||
| 	case *rsa.PublicKey: |  | ||||||
| 		der = x509.MarshalPKCS1PublicKey(k) |  | ||||||
| 		typ = "RSA PUBLIC KEY" |  | ||||||
| 	case *ecdsa.PublicKey: |  | ||||||
| 		typ = "PUBLIC KEY" |  | ||||||
| 		der, err = x509.MarshalPKIXPublicKey(k) |  | ||||||
| 		if nil != err { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	default: |  | ||||||
| 		panic("Developer Error: impossible key type") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return &pem.Block{ |  | ||||||
| 		Bytes: der, |  | ||||||
| 		Type:  typ, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MarshalJWKPrivateKey outputs the given private key as JWK |  | ||||||
| func MarshalJWKPrivateKey(privkey PrivateKey) []byte { |  | ||||||
| 	// thumbprint keys are alphabetically sorted and only include the necessary public parts |  | ||||||
| 	switch k := privkey.(type) { |  | ||||||
| 	case *rsa.PrivateKey: |  | ||||||
| 		return MarshalRSAPrivateKey(k) |  | ||||||
| 	case *ecdsa.PrivateKey: |  | ||||||
| 		return MarshalECPrivateKey(k) |  | ||||||
| 	default: |  | ||||||
| 		// this is unreachable because we know the types that we pass in |  | ||||||
| 		log.Printf("keytype: %t, %+v\n", privkey, privkey) |  | ||||||
| 		panic(ErrInvalidPublicKey) |  | ||||||
| 		//return nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MarshalDERPrivateKey outputs the given private key as ASN.1 DER |  | ||||||
| func MarshalDERPrivateKey(privkey PrivateKey) ([]byte, error) { |  | ||||||
| 	// thumbprint keys are alphabetically sorted and only include the necessary public parts |  | ||||||
| 	switch k := privkey.(type) { |  | ||||||
| 	case *rsa.PrivateKey: |  | ||||||
| 		return x509.MarshalPKCS1PrivateKey(k), nil |  | ||||||
| 	case *ecdsa.PrivateKey: |  | ||||||
| 		return x509.MarshalECPrivateKey(k) |  | ||||||
| 	default: |  | ||||||
| 		// this is unreachable because we know the types that we pass in |  | ||||||
| 		log.Printf("keytype: %t, %+v\n", privkey, privkey) |  | ||||||
| 		panic(ErrInvalidPublicKey) |  | ||||||
| 		//return nil, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func marshalDERPrivateKey(privkey PrivateKey) (*pem.Block, error) { |  | ||||||
| 	var typ string |  | ||||||
| 	var bytes []byte |  | ||||||
| 	var err error |  | ||||||
| 
 |  | ||||||
| 	switch k := privkey.(type) { |  | ||||||
| 	case *rsa.PrivateKey: |  | ||||||
| 		if 0 == mathrand.Intn(2) { |  | ||||||
| 			typ = "PRIVATE KEY" |  | ||||||
| 			bytes, err = x509.MarshalPKCS8PrivateKey(k) |  | ||||||
| 			if nil != err { |  | ||||||
| 				return nil, err |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			typ = "RSA PRIVATE KEY" |  | ||||||
| 			bytes = x509.MarshalPKCS1PrivateKey(k) |  | ||||||
| 		} |  | ||||||
| 		return &pem.Block{ |  | ||||||
| 			Type:  typ, |  | ||||||
| 			Bytes: bytes, |  | ||||||
| 		}, nil |  | ||||||
| 	case *ecdsa.PrivateKey: |  | ||||||
| 		if 0 == mathrand.Intn(2) { |  | ||||||
| 			typ = "PRIVATE KEY" |  | ||||||
| 			bytes, err = x509.MarshalPKCS8PrivateKey(k) |  | ||||||
| 		} else { |  | ||||||
| 			typ = "EC PRIVATE KEY" |  | ||||||
| 			bytes, err = x509.MarshalECPrivateKey(k) |  | ||||||
| 		} |  | ||||||
| 		if nil != err { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		return &pem.Block{ |  | ||||||
| 			Type:  typ, |  | ||||||
| 			Bytes: bytes, |  | ||||||
| 		}, nil |  | ||||||
| 	default: |  | ||||||
| 		// this is unreachable because we know the types that we pass in |  | ||||||
| 		log.Printf("keytype: %t, %+v\n", privkey, privkey) |  | ||||||
| 		panic(ErrInvalidPublicKey) |  | ||||||
| 		//return nil, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MarshalPEMPrivateKey outputs the given private key as ASN.1 PEM |  | ||||||
| func MarshalPEMPrivateKey(privkey PrivateKey) ([]byte, error) { |  | ||||||
| 	block, err := marshalDERPrivateKey(privkey) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return pem.EncodeToMemory(block), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MarshalECPrivateKey will output the given private key as JWK |  | ||||||
| func MarshalECPrivateKey(k *ecdsa.PrivateKey) []byte { |  | ||||||
| 	crv := k.Curve.Params().Name |  | ||||||
| 	d := base64.RawURLEncoding.EncodeToString(k.D.Bytes()) |  | ||||||
| 	x := base64.RawURLEncoding.EncodeToString(k.X.Bytes()) |  | ||||||
| 	y := base64.RawURLEncoding.EncodeToString(k.Y.Bytes()) |  | ||||||
| 	return []byte(fmt.Sprintf( |  | ||||||
| 		`{"crv":%q,"d":%q,"kty":"EC","x":%q,"y":%q}`, |  | ||||||
| 		crv, d, x, y, |  | ||||||
| 	)) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MarshalRSAPrivateKey will output the given private key as JWK |  | ||||||
| func MarshalRSAPrivateKey(pk *rsa.PrivateKey) []byte { |  | ||||||
| 	e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pk.E)).Bytes()) |  | ||||||
| 	n := base64.RawURLEncoding.EncodeToString(pk.N.Bytes()) |  | ||||||
| 	d := base64.RawURLEncoding.EncodeToString(pk.D.Bytes()) |  | ||||||
| 	p := base64.RawURLEncoding.EncodeToString(pk.Primes[0].Bytes()) |  | ||||||
| 	q := base64.RawURLEncoding.EncodeToString(pk.Primes[1].Bytes()) |  | ||||||
| 	dp := base64.RawURLEncoding.EncodeToString(pk.Precomputed.Dp.Bytes()) |  | ||||||
| 	dq := base64.RawURLEncoding.EncodeToString(pk.Precomputed.Dq.Bytes()) |  | ||||||
| 	qi := base64.RawURLEncoding.EncodeToString(pk.Precomputed.Qinv.Bytes()) |  | ||||||
| 	return []byte(fmt.Sprintf( |  | ||||||
| 		`{"d":%q,"dp":%q,"dq":%q,"e":%q,"kty":"RSA","n":%q,"p":%q,"q":%q,"qi":%q}`, |  | ||||||
| 		d, dp, dq, e, n, p, q, qi, |  | ||||||
| 	)) |  | ||||||
| } |  | ||||||
							
								
								
									
										46
									
								
								vendor/git.rootprojects.org/root/keypairs/mock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/git.rootprojects.org/root/keypairs/mock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,46 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"crypto/rsa" |  | ||||||
| 	"io" |  | ||||||
| 	"log" |  | ||||||
| 	mathrand "math/rand" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // this shananigans is only for testing and debug API stuff |  | ||||||
| func (o *keyOptions) maybeMockReader() io.Reader { |  | ||||||
| 	if !allowMocking { |  | ||||||
| 		panic("mock method called when mocking is not allowed") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if 0 == o.mockSeed { |  | ||||||
| 		return randReader |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	log.Println("WARNING: MOCK: using insecure reader") |  | ||||||
| 	return mathrand.New(mathrand.NewSource(o.mockSeed)) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const maxRetry = 16 |  | ||||||
| 
 |  | ||||||
| func maybeDerandomizeMockKey(privkey PrivateKey, keylen int, opts *keyOptions) PrivateKey { |  | ||||||
| 	if 0 != opts.mockSeed { |  | ||||||
| 		for i := 0; i < maxRetry; i++ { |  | ||||||
| 			otherkey, _ := rsa.GenerateKey(opts.nextReader(), keylen) |  | ||||||
| 			otherCmp := otherkey.D.Cmp(privkey.(*rsa.PrivateKey).D) |  | ||||||
| 			if 0 != otherCmp { |  | ||||||
| 				// There are two possible keys, choose the lesser D value |  | ||||||
| 				// See https://github.com/square/go-jose/issues/189 |  | ||||||
| 				if otherCmp < 0 { |  | ||||||
| 					privkey = otherkey |  | ||||||
| 				} |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 			if maxRetry == i-1 { |  | ||||||
| 				log.Printf("error: coinflip landed on heads %d times", maxRetry) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return privkey |  | ||||||
| } |  | ||||||
							
								
								
									
										165
									
								
								vendor/git.rootprojects.org/root/keypairs/sign.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										165
									
								
								vendor/git.rootprojects.org/root/keypairs/sign.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,165 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"crypto" |  | ||||||
| 	"crypto/ecdsa" |  | ||||||
| 	"crypto/rsa" |  | ||||||
| 	"crypto/sha256" |  | ||||||
| 	"encoding/base64" |  | ||||||
| 	"encoding/json" |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	mathrand "math/rand" // to be used for good, not evil |  | ||||||
| 	"time" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // Object is a type alias representing generic JSON data |  | ||||||
| type Object = map[string]interface{} |  | ||||||
| 
 |  | ||||||
| // SignClaims adds `typ`, `kid` (or `jwk`), and `alg` in the header and expects claims for `jti`, `exp`, `iss`, and `iat` |  | ||||||
| func SignClaims(privkey PrivateKey, header Object, claims Object) (*JWS, error) { |  | ||||||
| 	var randsrc io.Reader = randReader |  | ||||||
| 	seed, _ := header["_seed"].(int64) |  | ||||||
| 	if 0 != seed { |  | ||||||
| 		randsrc = mathrand.New(mathrand.NewSource(seed)) |  | ||||||
| 		//delete(header, "_seed") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	protected, header, err := headerToProtected(NewPublicKey(privkey.Public()), header) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	protected64 := base64.RawURLEncoding.EncodeToString(protected) |  | ||||||
| 
 |  | ||||||
| 	payload, err := claimsToPayload(claims) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	payload64 := base64.RawURLEncoding.EncodeToString(payload) |  | ||||||
| 
 |  | ||||||
| 	signable := fmt.Sprintf(`%s.%s`, protected64, payload64) |  | ||||||
| 	hash := sha256.Sum256([]byte(signable)) |  | ||||||
| 
 |  | ||||||
| 	sig := Sign(privkey, hash[:], randsrc) |  | ||||||
| 	sig64 := base64.RawURLEncoding.EncodeToString(sig) |  | ||||||
| 	//log.Printf("\n(Sign)\nSignable: %s", signable) |  | ||||||
| 	//log.Printf("Hash: %s", hash) |  | ||||||
| 	//log.Printf("Sig: %s", sig64) |  | ||||||
| 
 |  | ||||||
| 	return &JWS{ |  | ||||||
| 		Header:    header, |  | ||||||
| 		Claims:    claims, |  | ||||||
| 		Protected: protected64, |  | ||||||
| 		Payload:   payload64, |  | ||||||
| 		Signature: sig64, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func headerToProtected(pub PublicKey, header Object) ([]byte, Object, error) { |  | ||||||
| 	if nil == header { |  | ||||||
| 		header = Object{} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Only supporting 2048-bit and P256 keys right now |  | ||||||
| 	// because that's all that's practical and well-supported. |  | ||||||
| 	// No security theatre here. |  | ||||||
| 	alg := "ES256" |  | ||||||
| 	switch pub.Key().(type) { |  | ||||||
| 	case *rsa.PublicKey: |  | ||||||
| 		alg = "RS256" |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if selfSign, _ := header["_jwk"].(bool); selfSign { |  | ||||||
| 		delete(header, "_jwk") |  | ||||||
| 		any := Object{} |  | ||||||
| 		_ = json.Unmarshal(MarshalJWKPublicKey(pub), &any) |  | ||||||
| 		header["jwk"] = any |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// TODO what are the acceptable values? JWT. JWS? others? |  | ||||||
| 	header["typ"] = "JWT" |  | ||||||
| 	if _, ok := header["jwk"]; !ok { |  | ||||||
| 		thumbprint := ThumbprintPublicKey(pub) |  | ||||||
| 		kid, _ := header["kid"].(string) |  | ||||||
| 		if "" != kid && thumbprint != kid { |  | ||||||
| 			return nil, nil, errors.New("'kid' should be the key's thumbprint") |  | ||||||
| 		} |  | ||||||
| 		header["kid"] = thumbprint |  | ||||||
| 	} |  | ||||||
| 	header["alg"] = alg |  | ||||||
| 
 |  | ||||||
| 	protected, err := json.Marshal(header) |  | ||||||
| 	if nil != err { |  | ||||||
| 		return nil, nil, err |  | ||||||
| 	} |  | ||||||
| 	return protected, header, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func claimsToPayload(claims Object) ([]byte, error) { |  | ||||||
| 	if nil == claims { |  | ||||||
| 		claims = Object{} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var dur time.Duration |  | ||||||
| 	jti, _ := claims["jti"].(string) |  | ||||||
| 	insecure, _ := claims["insecure"].(bool) |  | ||||||
| 
 |  | ||||||
| 	switch exp := claims["exp"].(type) { |  | ||||||
| 	case time.Duration: |  | ||||||
| 		// TODO: MUST this go first? |  | ||||||
| 		// int64(time.Duration) vs time.Duration(int64) |  | ||||||
| 		dur = exp |  | ||||||
| 	case string: |  | ||||||
| 		var err error |  | ||||||
| 		dur, err = time.ParseDuration(exp) |  | ||||||
| 		// TODO s, err := time.ParseDuration(dur) |  | ||||||
| 		if nil != err { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	case int: |  | ||||||
| 		dur = time.Second * time.Duration(exp) |  | ||||||
| 	case int64: |  | ||||||
| 		dur = time.Second * time.Duration(exp) |  | ||||||
| 	case float64: |  | ||||||
| 		dur = time.Second * time.Duration(exp) |  | ||||||
| 	default: |  | ||||||
| 		dur = 0 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if "" == jti && 0 == dur && !insecure { |  | ||||||
| 		return nil, errors.New("token must have jti or exp as to be expirable / cancellable") |  | ||||||
| 	} |  | ||||||
| 	claims["exp"] = time.Now().Add(dur).Unix() |  | ||||||
| 
 |  | ||||||
| 	return json.Marshal(claims) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Sign signs both RSA and ECDSA. Use `nil` or `crypto/rand.Reader` except for debugging. |  | ||||||
| func Sign(privkey PrivateKey, hash []byte, rand io.Reader) []byte { |  | ||||||
| 	if nil == rand { |  | ||||||
| 		rand = randReader |  | ||||||
| 	} |  | ||||||
| 	var sig []byte |  | ||||||
| 
 |  | ||||||
| 	if len(hash) != 32 { |  | ||||||
| 		panic("only 256-bit hashes for 2048-bit and 256-bit keys are supported") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	switch k := privkey.(type) { |  | ||||||
| 	case *rsa.PrivateKey: |  | ||||||
| 		sig, _ = rsa.SignPKCS1v15(rand, k, crypto.SHA256, hash) |  | ||||||
| 	case *ecdsa.PrivateKey: |  | ||||||
| 		r, s, _ := ecdsa.Sign(rand, k, hash[:]) |  | ||||||
| 		rb := r.Bytes() |  | ||||||
| 		for len(rb) < 32 { |  | ||||||
| 			rb = append([]byte{0}, rb...) |  | ||||||
| 		} |  | ||||||
| 		sb := s.Bytes() |  | ||||||
| 		for len(rb) < 32 { |  | ||||||
| 			sb = append([]byte{0}, sb...) |  | ||||||
| 		} |  | ||||||
| 		sig = append(rb, sb...) |  | ||||||
| 	} |  | ||||||
| 	return sig |  | ||||||
| } |  | ||||||
							
								
								
									
										174
									
								
								vendor/git.rootprojects.org/root/keypairs/verify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										174
									
								
								vendor/git.rootprojects.org/root/keypairs/verify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,174 +0,0 @@ | |||||||
| package keypairs |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"crypto" |  | ||||||
| 	"crypto/ecdsa" |  | ||||||
| 	"crypto/rsa" |  | ||||||
| 	"crypto/sha256" |  | ||||||
| 	"crypto/subtle" |  | ||||||
| 	"encoding/base64" |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"log" |  | ||||||
| 	"math/big" |  | ||||||
| 	"time" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // VerifyClaims will check the signature of a parsed JWT |  | ||||||
| func VerifyClaims(pubkey PublicKey, jws *JWS) (errs []error) { |  | ||||||
| 	kid, _ := jws.Header["kid"].(string) |  | ||||||
| 	jwkmap, hasJWK := jws.Header["jwk"].(Object) |  | ||||||
| 	//var jwk JWK = nil |  | ||||||
| 
 |  | ||||||
| 	seed, _ := jws.Header["_seed"].(int64) |  | ||||||
| 	seedf64, _ := jws.Header["_seed"].(float64) |  | ||||||
| 	kty, _ := jws.Header["_kty"].(string) |  | ||||||
| 	if 0 == seed { |  | ||||||
| 		seed = int64(seedf64) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var pub PublicKey = nil |  | ||||||
| 	if hasJWK { |  | ||||||
| 		pub, errs = selfsignCheck(jwkmap, errs) |  | ||||||
| 	} else { |  | ||||||
| 		opts := &keyOptions{mockSeed: seed, KeyType: kty} |  | ||||||
| 		pub, errs = pubkeyCheck(pubkey, kid, opts, errs) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	jti, _ := jws.Claims["jti"].(string) |  | ||||||
| 	expf64, _ := jws.Claims["exp"].(float64) |  | ||||||
| 	exp := int64(expf64) |  | ||||||
| 	if 0 == exp { |  | ||||||
| 		if "" == jti { |  | ||||||
| 			err := errors.New("one of 'jti' or 'exp' must exist for token expiry") |  | ||||||
| 			errs = append(errs, err) |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		if time.Now().Unix() > exp { |  | ||||||
| 			err := fmt.Errorf("token expired at %d (%s)", exp, time.Unix(exp, 0)) |  | ||||||
| 			errs = append(errs, err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	signable := fmt.Sprintf("%s.%s", jws.Protected, jws.Payload) |  | ||||||
| 	hash := sha256.Sum256([]byte(signable)) |  | ||||||
| 	sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) |  | ||||||
| 	if nil != err { |  | ||||||
| 		err := fmt.Errorf("could not decode signature: %w", err) |  | ||||||
| 		errs = append(errs, err) |  | ||||||
| 		return errs |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	//log.Printf("\n(Verify)\nSignable: %s", signable) |  | ||||||
| 	//log.Printf("Hash: %s", hash) |  | ||||||
| 	//log.Printf("Sig: %s", jws.Signature) |  | ||||||
| 	if nil == pub { |  | ||||||
| 		err := fmt.Errorf("token signature could not be verified") |  | ||||||
| 		errs = append(errs, err) |  | ||||||
| 	} else if !Verify(pub, hash[:], sig) { |  | ||||||
| 		err := fmt.Errorf("token signature is not valid") |  | ||||||
| 		errs = append(errs, err) |  | ||||||
| 	} |  | ||||||
| 	return errs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func selfsignCheck(jwkmap Object, errs []error) (PublicKey, []error) { |  | ||||||
| 	var pub PublicKey = nil |  | ||||||
| 	log.Println("Security TODO: did not check jws.Claims[\"sub\"] against 'jwk'") |  | ||||||
| 	log.Println("Security TODO: did not check jws.Claims[\"iss\"]") |  | ||||||
| 	kty := jwkmap["kty"] |  | ||||||
| 	var err error |  | ||||||
| 	if "RSA" == kty { |  | ||||||
| 		e, _ := jwkmap["e"].(string) |  | ||||||
| 		n, _ := jwkmap["n"].(string) |  | ||||||
| 		k, _ := (&RSAJWK{ |  | ||||||
| 			Exp: e, |  | ||||||
| 			N:   n, |  | ||||||
| 		}).marshalJWK() |  | ||||||
| 		pub, err = ParseJWKPublicKey(k) |  | ||||||
| 		if nil != err { |  | ||||||
| 			return nil, append(errs, err) |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		crv, _ := jwkmap["crv"].(string) |  | ||||||
| 		x, _ := jwkmap["x"].(string) |  | ||||||
| 		y, _ := jwkmap["y"].(string) |  | ||||||
| 		k, _ := (&ECJWK{ |  | ||||||
| 			Curve: crv, |  | ||||||
| 			X:     x, |  | ||||||
| 			Y:     y, |  | ||||||
| 		}).marshalJWK() |  | ||||||
| 		pub, err = ParseJWKPublicKey(k) |  | ||||||
| 		if nil != err { |  | ||||||
| 			return nil, append(errs, err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return pub, errs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func pubkeyCheck(pubkey PublicKey, kid string, opts *keyOptions, errs []error) (PublicKey, []error) { |  | ||||||
| 	var pub PublicKey = nil |  | ||||||
| 
 |  | ||||||
| 	if "" == kid { |  | ||||||
| 		err := errors.New("token should have 'kid' or 'jwk' in header to identify the public key") |  | ||||||
| 		errs = append(errs, err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if nil == pubkey { |  | ||||||
| 		if allowMocking { |  | ||||||
| 			if 0 == opts.mockSeed { |  | ||||||
| 				err := errors.New("the debug API requires '_seed' to accompany 'kid'") |  | ||||||
| 				errs = append(errs, err) |  | ||||||
| 			} |  | ||||||
| 			if "" == opts.KeyType { |  | ||||||
| 				err := errors.New("the debug API requires '_kty' to accompany '_seed'") |  | ||||||
| 				errs = append(errs, err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if 0 == opts.mockSeed || "" == opts.KeyType { |  | ||||||
| 				return nil, errs |  | ||||||
| 			} |  | ||||||
| 			privkey := newPrivateKey(opts) |  | ||||||
| 			pub = NewPublicKey(privkey.Public()) |  | ||||||
| 			return pub, errs |  | ||||||
| 		} |  | ||||||
| 		err := errors.New("no matching public key") |  | ||||||
| 		errs = append(errs, err) |  | ||||||
| 	} else { |  | ||||||
| 		pub = pubkey |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if nil != pub && "" != kid { |  | ||||||
| 		if 1 != subtle.ConstantTimeCompare([]byte(kid), []byte(pub.Thumbprint())) { |  | ||||||
| 			err := errors.New("'kid' does not match the public key thumbprint") |  | ||||||
| 			errs = append(errs, err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return pub, errs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Verify will check the signature of a hash |  | ||||||
| func Verify(pubkey PublicKey, hash []byte, sig []byte) bool { |  | ||||||
| 
 |  | ||||||
| 	switch pub := pubkey.Key().(type) { |  | ||||||
| 	case *rsa.PublicKey: |  | ||||||
| 		//log.Printf("RSA VERIFY") |  | ||||||
| 		// TODO Size(key) to detect key size ? |  | ||||||
| 		//alg := "SHA256" |  | ||||||
| 		// TODO: this hasn't been tested yet |  | ||||||
| 		if err := rsa.VerifyPKCS1v15(pub, crypto.SHA256, hash, sig); nil != err { |  | ||||||
| 			return false |  | ||||||
| 		} |  | ||||||
| 		return true |  | ||||||
| 	case *ecdsa.PublicKey: |  | ||||||
| 		r := &big.Int{} |  | ||||||
| 		r.SetBytes(sig[0:32]) |  | ||||||
| 		s := &big.Int{} |  | ||||||
| 		s.SetBytes(sig[32:]) |  | ||||||
| 		return ecdsa.Verify(pub, hash, r, s) |  | ||||||
| 	default: |  | ||||||
| 		panic("impossible condition: non-rsa/non-ecdsa key") |  | ||||||
| 		//return false |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| # git.rootprojects.org/root/hashcash v1.0.1 | # git.rootprojects.org/root/hashcash v1.0.1 | ||||||
| git.rootprojects.org/root/hashcash | git.rootprojects.org/root/hashcash | ||||||
| # git.rootprojects.org/root/keypairs v0.6.5 | # git.rootprojects.org/root/keypairs v0.5.2 | ||||||
| git.rootprojects.org/root/keypairs | git.rootprojects.org/root/keypairs | ||||||
| git.rootprojects.org/root/keypairs/keyfetch | git.rootprojects.org/root/keypairs/keyfetch | ||||||
| git.rootprojects.org/root/keypairs/keyfetch/uncached | git.rootprojects.org/root/keypairs/keyfetch/uncached | ||||||
|  | |||||||
| @ -3,30 +3,22 @@ package xkeypairs | |||||||
| import ( | import ( | ||||||
| 	"crypto/ecdsa" | 	"crypto/ecdsa" | ||||||
| 	"crypto/elliptic" | 	"crypto/elliptic" | ||||||
| 	"crypto/rand" |  | ||||||
| 	"crypto/rsa" | 	"crypto/rsa" | ||||||
| 	"io" | 	"io" | ||||||
| 	"log" | 	"log" | ||||||
| 	mathrand "math/rand" | 	"math/rand" | ||||||
| 
 | 
 | ||||||
| 	"git.rootprojects.org/root/keypairs" | 	"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 | // KeyOptions are the things that we may need to know about a request to fulfill it properly | ||||||
| type KeyOptions struct { | type KeyOptions struct { | ||||||
| 	Key     string `json:"key"` | 	Key     string `json:"key"` | ||||||
| 	KeyType string `json:"kty"` | 	KeyType string `json:"kty"` | ||||||
| 	Seed    int64  `json:"-"` | 	Seed    int64  `json:"-"` | ||||||
| 	SeedStr string `json:"seed"` | 	SeedStr string `json:"seed"` | ||||||
| 	Claims  keypairs.Object `json:"claims"` | 	Claims  Object `json:"claims"` | ||||||
| 	Header  keypairs.Object `json:"header"` | 	Header  Object `json:"header"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // this shananigans is only for testing and debug API stuff | // this shananigans is only for testing and debug API stuff | ||||||
| @ -34,7 +26,7 @@ func (o *KeyOptions) MyFooNextReader() io.Reader { | |||||||
| 	if 0 == o.Seed { | 	if 0 == o.Seed { | ||||||
| 		return RandomReader | 		return RandomReader | ||||||
| 	} | 	} | ||||||
| 	return mathrand.New(mathrand.NewSource(o.Seed)) | 	return rand.New(rand.NewSource(o.Seed)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GenPrivKey generates a 256-bit entropy RSA or ECDSA private key | // GenPrivKey generates a 256-bit entropy RSA or ECDSA private key | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user