| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"crypto/sha256" | 
					
						
							|  |  |  | 	"encoding/binary" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"math/rand" | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 	mathrand "math/rand" | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 07:09:43 +00:00
										 |  |  | type Object = map[string]interface{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | // options are the things that we may need to know about a request to fulfill it properly | 
					
						
							|  |  |  | type options struct { | 
					
						
							| 
									
										
										
										
											2020-08-02 09:39:56 +00:00
										 |  |  | 	Key     string `json:"key"` | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 	KeyType string `json:"kty"` | 
					
						
							|  |  |  | 	Seed    int64  `json:"-"` | 
					
						
							|  |  |  | 	SeedStr string `json:"seed"` | 
					
						
							| 
									
										
										
										
											2020-08-04 07:09:43 +00:00
										 |  |  | 	Claims  Object `json:"claims"` | 
					
						
							|  |  |  | 	Header  Object `json:"header"` | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // this shananigans is only for testing and debug API stuff | 
					
						
							|  |  |  | func (o *options) nextReader() io.Reader { | 
					
						
							|  |  |  | 	if 0 == o.Seed { | 
					
						
							|  |  |  | 		return RandomReader | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return rand.New(rand.NewSource(o.Seed)) | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 08:13:32 +00:00
										 |  |  | /* | 
					
						
							|  |  |  | func getJWS(r *http.Request) (*options, error) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | func getOpts(r *http.Request) (*options, error) { | 
					
						
							|  |  |  | 	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])) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 09:39:56 +00:00
										 |  |  | 	key, _ := tok["key"].(string) | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 	opts := &options{ | 
					
						
							|  |  |  | 		Seed: seed, | 
					
						
							| 
									
										
										
										
											2020-08-02 09:39:56 +00:00
										 |  |  | 		Key:  key, | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 07:09:43 +00:00
										 |  |  | 	opts.Claims, _ = tok["claims"].(Object) | 
					
						
							|  |  |  | 	opts.Header, _ = tok["header"].(Object) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 00:11:50 +00:00
										 |  |  | 	var n int | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | 	if 0 != seed { | 
					
						
							| 
									
										
										
										
											2020-08-02 09:39:56 +00:00
										 |  |  | 		n = opts.nextReader().(*mathrand.Rand).Intn(2) | 
					
						
							| 
									
										
										
										
											2020-08-02 00:11:50 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		n = rand.Intn(2) | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 	opts.KeyType, _ = tok["kty"].(string) | 
					
						
							|  |  |  | 	if "" == opts.KeyType { | 
					
						
							| 
									
										
										
										
											2020-08-02 00:11:50 +00:00
										 |  |  | 		if 0 == n { | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 			opts.KeyType = "RSA" | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 			opts.KeyType = "EC" | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 08:16:28 +00:00
										 |  |  | 	return opts, nil | 
					
						
							| 
									
										
										
										
											2020-08-01 23:59:20 +00:00
										 |  |  | } |