package api import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/rsa" "io" "log" "net/http" "git.coolaj86.com/coolaj86/go-mockid/xkeypairs" "git.rootprojects.org/root/keypairs" ) // RandomReader may be overwritten for testing var RandomReader io.Reader = rand.Reader // GeneratePrivateJWK will create a new private key in JWK format func GeneratePrivateJWK(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.Method, r.URL.Path) if "POST" != r.Method { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } opts, err := getOpts(r) if nil != err { http.Error(w, err.Error(), http.StatusBadRequest) return } privkey := genPrivKey(opts) jwk := xkeypairs.MarshalJWKPrivateKey(privkey) w.Write(append(jwk, '\n')) } // GeneratePrivateDER will create a new private key in a valid DER encoding func GeneratePrivateDER(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.Method, r.URL.Path) if "POST" != r.Method { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } opts, err := getOpts(r) if nil != err { http.Error(w, err.Error(), http.StatusBadRequest) return } privkey := genPrivKey(opts) der, _ := xkeypairs.MarshalDERPrivateKey(privkey) w.Write(der) } // GeneratePrivatePEM will create a new private key in a valid PEM encoding func GeneratePrivatePEM(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.Method, r.URL.Path) if "POST" != r.Method { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } opts, err := getOpts(r) if nil != err { http.Error(w, err.Error(), http.StatusBadRequest) return } privkey := genPrivKey(opts) privpem, _ := xkeypairs.MarshalPEMPrivateKey(privkey) w.Write(privpem) } func genPrivKey(opts *options) keypairs.PrivateKey { var privkey keypairs.PrivateKey if "RSA" == opts.KeyType { keylen := 2048 rndReader := opts.nextReader() privkey, _ = rsa.GenerateKey(rndReader, keylen) if rndReader != RandomReader { for i := 0; i < 16; i++ { otherkey, _ := rsa.GenerateKey(opts.nextRand(), 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 } } } } else { privkey, _ = ecdsa.GenerateKey(elliptic.P256(), opts.nextReader()) } return privkey }