package api import ( "bytes" "crypto/sha256" "encoding/binary" "encoding/json" "errors" "io" "log" "math/rand" "net/http" ) // options are the things that we may need to know about a request to fulfill it properly type options struct { KeyType string `json:"kty"` Seed int64 `json:"-"` SeedStr string `json:"seed"` rndReader io.Reader `json:"-"` } func getOpts(r *http.Request) (*options, error) { rndReader := RandomReader tok := make(map[string]interface{}) decoder := json.NewDecoder(r.Body) err := decoder.Decode(&tok) if nil != err && io.EOF != err { log.Printf("json decode error: %s", err) return nil, errors.New("Bad Request: invalid json body") } defer r.Body.Close() var seed int64 seedStr, _ := tok["seed"].(string) if "" != seedStr { if len(seedStr) > 256 { return nil, errors.New("Bad Request: base64 seed should be <256 characters (and is truncated to 64-bits anyway)") } b := sha256.Sum256([]byte(seedStr)) seed, _ = binary.ReadVarint(bytes.NewReader(b[0:8])) } var n int if 0 != seed { rnd := rand.New(rand.NewSource(seed)) rndReader = rnd n = rnd.Intn(2) } else { n = rand.Intn(2) } kty, _ := tok["kty"].(string) if "" == kty { if 0 == n { kty = "RSA" } else { kty = "EC" } } return &options{ KeyType: kty, Seed: seed, rndReader: rndReader, }, nil }