keypairs/generate.go

84 lines
2.0 KiB
Go

package keypairs
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"io"
mathrand "math/rand"
"time"
)
var randReader io.Reader = rand.Reader
var maxRetry = 1
// 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 {
return randReader
/*
if 0 == o.Seed {
return randReader
}
return mathrand.New(mathrand.NewSource(o.Seed))
*/
}
// NewDefaultPrivateKey generates a key with reasonable strength.
// Today that means a 256-bit equivalent - either RSA 2048 or EC P-256.
func NewDefaultPrivateKey() PrivateKey {
mathrand.Seed(time.Now().UnixNano())
coin := mathrand.Int()
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.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
}