package xkeypairs import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" "io" "log" "math/rand" "git.rootprojects.org/root/keypairs" ) // 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"` } // this shananigans is only for testing and debug API stuff func (o *KeyOptions) MyFooNextReader() io.Reader { if 0 == o.Seed { return RandomReader } return rand.New(rand.NewSource(o.Seed)) } // GenPrivKey generates a 256-bit entropy RSA or ECDSA private key func GenPrivKey(opts *KeyOptions) keypairs.PrivateKey { var privkey keypairs.PrivateKey if "RSA" == opts.KeyType { keylen := 2048 privkey, _ = rsa.GenerateKey(opts.MyFooNextReader(), keylen) if 0 != opts.Seed { for i := 0; i < maxRetry; i++ { otherkey, _ := rsa.GenerateKey(opts.MyFooNextReader(), 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) } } } } else { // TODO: EC keys may also suffer the same random problems in the future privkey, _ = ecdsa.GenerateKey(elliptic.P256(), opts.MyFooNextReader()) } return privkey }