62 lines
1.6 KiB
Go
62 lines
1.6 KiB
Go
|
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
|
||
|
}
|