aboutsummaryrefslogtreecommitdiff
path: root/descriptor
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-11-05 16:07:22 +0100
committerRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-11-05 16:07:22 +0100
commit36743a05a39f449628b153f1051bd854cf4ed6aa (patch)
tree8eb7bca431849c78d9d3a6fc086a762a0ae0f89c /descriptor
parent2cd6104d601cb3a064b7b67ecf097a8591c029dd (diff)
moved package from stfe/server/descriptor to stfe/descriptor
Diffstat (limited to 'descriptor')
-rw-r--r--descriptor/descriptor.go62
-rw-r--r--descriptor/descriptor_test.go96
-rw-r--r--descriptor/stfe.json18
3 files changed, 176 insertions, 0 deletions
diff --git a/descriptor/descriptor.go b/descriptor/descriptor.go
new file mode 100644
index 0000000..267a401
--- /dev/null
+++ b/descriptor/descriptor.go
@@ -0,0 +1,62 @@
+package descriptor
+
+import (
+ "bytes"
+ "fmt"
+
+ "crypto"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/json"
+ "io/ioutil"
+)
+
+// Operator is an stfe log operator that runs zero or more logs
+type Operator struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ Logs []*Log `json:"logs"`
+}
+
+// Log is a collection of immutable stfe log parameters
+type Log struct {
+ Id []byte `json:"id"` // H(PublicKey)
+ PublicKey []byte `json:"public_key"` // DER-encoded SubjectPublicKeyInfo
+ Scheme tls.SignatureScheme `json:"signature_scheme"` // Signature schemes used by the log (RFC 8446, §4.2.3)
+ Schemes []tls.SignatureScheme `json:"signature_schemes"` // Signature schemes that submitters can use (RFC 8446, §4.2.3)
+ MaxChain uint8 `json:"max_chain"` // maximum certificate chain length
+ BaseUrl string `json:"base_url"` // E.g., example.com/st/v1
+}
+
+func FindLog(ops []Operator, logId []byte) (*Log, error) {
+ for _, op := range ops {
+ for _, log := range op.Logs {
+ if bytes.Equal(logId, log.Id) {
+ return log, nil
+ }
+ }
+ }
+ return nil, fmt.Errorf("no such log: %s", base64.StdEncoding.EncodeToString(logId))
+}
+
+// LoadOperators loads a list of json-encoded log operators from a given path
+func LoadOperators(path string) ([]Operator, error) {
+ blob, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("failed reading log operators: %v", err)
+ }
+ var ops []Operator
+ if err := json.Unmarshal(blob, &ops); err != nil {
+ return nil, fmt.Errorf("failed decoding log operators: %v", err)
+ }
+ return ops, nil
+}
+
+func (l *Log) Key() crypto.PublicKey {
+ k, err := x509.ParsePKIXPublicKey(l.PublicKey)
+ if err != nil {
+ panic("TODO: make a new function and parse public key there")
+ }
+ return k
+}
diff --git a/descriptor/descriptor_test.go b/descriptor/descriptor_test.go
new file mode 100644
index 0000000..d01fc66
--- /dev/null
+++ b/descriptor/descriptor_test.go
@@ -0,0 +1,96 @@
+package descriptor
+
+import (
+ "fmt"
+ "testing"
+
+ "crypto/sha256"
+ "crypto/tls"
+ "encoding/base64"
+ "encoding/json"
+)
+
+const (
+ operatorListJson = `[{"name":"Test operator","email":"test@example.com","logs":[{"id":"B9oCJk4XIOMXba8dBM5yUj+NLtqTE6xHwbvR9dYkHPM=","public_key":"MCowBQYDK2VwAyEAqM4b/SHOCRId9xgiCPn8D8r6+Nrk9JTZZqW6vj7TGa0=","signature_scheme":2055,"signature_schemes":[2055],"max_chain":3,"base_url":"example.com/st/v1"}]}]`
+)
+
+func TestMarshal(t *testing.T) {
+ for _, table := range []struct {
+ in []Operator
+ want string
+ }{
+ {makeOperatorList(), operatorListJson},
+ } {
+ b, err := json.Marshal(table.in)
+ if err != nil {
+ t.Errorf("operator list marshaling failed: %v", err)
+ }
+ if string(b) != table.want {
+ t.Errorf("\nwant %s\n got %s", table.want, string(b))
+ }
+ }
+
+}
+
+func TestUnmarshal(t *testing.T) {
+ for _, table := range []struct {
+ in []byte
+ want error
+ }{
+ {[]byte(operatorListJson), nil},
+ } {
+ var op []Operator
+ if err := json.Unmarshal(table.in, &op); err != table.want {
+ t.Errorf("wanted err=%v, got %v", table.want, err)
+ }
+ }
+}
+
+func TestFindLog(t *testing.T) {
+ for _, table := range []struct {
+ ops []Operator
+ logId []byte
+ wantError bool
+ }{
+ {makeOperatorList(), deb64("B9oCJk4XIOMXba8dBM5yUj+NLtqTE6xHwbvR9dYkHPM="), false},
+ {makeOperatorList(), []byte{0, 1, 2, 3}, true},
+ } {
+ _, err := FindLog(table.ops, table.logId)
+ if (err != nil) != table.wantError {
+ t.Errorf("wanted log not found for id: %v", table.logId)
+ }
+ }
+}
+
+func makeOperatorList() []Operator {
+ pub := deb64("MCowBQYDK2VwAyEAqM4b/SHOCRId9xgiCPn8D8r6+Nrk9JTZZqW6vj7TGa0=")
+ h := sha256.New()
+ h.Write(pub)
+ id := h.Sum(nil)
+ return []Operator{
+ Operator{
+ Name: "Test operator",
+ Email: "test@example.com",
+ Logs: []*Log{
+ &Log{
+ Id: id,
+ PublicKey: pub,
+ Scheme: tls.Ed25519,
+ Schemes: []tls.SignatureScheme{
+ tls.Ed25519,
+ },
+ MaxChain: 3,
+ BaseUrl: "example.com/st/v1",
+ },
+ },
+ },
+ }
+}
+
+func deb64(s string) []byte {
+ b, err := base64.StdEncoding.DecodeString(s)
+ if err != nil {
+ panic(fmt.Sprintf("failed decoding base64: %v", err))
+ }
+ return b
+}
diff --git a/descriptor/stfe.json b/descriptor/stfe.json
new file mode 100644
index 0000000..d987c47
--- /dev/null
+++ b/descriptor/stfe.json
@@ -0,0 +1,18 @@
+[
+ {
+ "name": "Test operator",
+ "email": "test@example.com",
+ "logs": [
+ {
+ "max_chain": 3,
+ "id": "B9oCJk4XIOMXba8dBM5yUj+NLtqTE6xHwbvR9dYkHPM=",
+ "signature_schemes": [
+ 2055
+ ],
+ "base_url": "localhost:6965/st/v1",
+ "signature_scheme": 2055,
+ "public_key": "MCowBQYDK2VwAyEAqM4b/SHOCRId9xgiCPn8D8r6+Nrk9JTZZqW6vj7TGa0="
+ }
+ ]
+ }
+]