diff options
| author | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2020-11-02 17:04:13 +0100 | 
|---|---|---|
| committer | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2020-11-02 17:04:13 +0100 | 
| commit | 801afaa9147c4f70fc00fde1993f6ce0c91bd450 (patch) | |
| tree | 6df8b964eeb4c1a95e693f11cb5b637bf9bb4ee2 /server/descriptor | |
| parent | 0b52f555fa06e9c4098caf76933ec8f923182982 (diff) | |
added stfe server descriptor
A collection of immutable log parameters, see documentation.
Diffstat (limited to 'server/descriptor')
| -rw-r--r-- | server/descriptor/descriptor.go | 40 | ||||
| -rw-r--r-- | server/descriptor/descriptor_test.go | 96 | ||||
| -rw-r--r-- | server/descriptor/stfe.json | 18 | 
3 files changed, 154 insertions, 0 deletions
| diff --git a/server/descriptor/descriptor.go b/server/descriptor/descriptor.go new file mode 100644 index 0000000..ba90289 --- /dev/null +++ b/server/descriptor/descriptor.go @@ -0,0 +1,40 @@ +package descriptor + +import ( +	"bytes" +	"fmt" + +	"crypto/tls" +	"encoding/base64" +) + +const ( +	// Location is an url to a json-encoded list of stfe log operators +	Location = "https://github.com/system-transparency/stfe/tree/main/server/descriptor/stfe.json" +) + +// 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 (op *Operator) FindLog(logId []byte) (*Log, error) { +	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)) +} diff --git a/server/descriptor/descriptor_test.go b/server/descriptor/descriptor_test.go new file mode 100644 index 0000000..e461f88 --- /dev/null +++ b/server/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 { +		op        Operator +		logId     []byte +		wantError bool +	}{ +		{makeOperatorList()[0], deb64("B9oCJk4XIOMXba8dBM5yUj+NLtqTE6xHwbvR9dYkHPM="), false}, +		{makeOperatorList()[0], []byte{0, 1, 2, 3}, true}, +	} { +		_, err := table.op.FindLog(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/server/descriptor/stfe.json b/server/descriptor/stfe.json new file mode 100644 index 0000000..69e84a0 --- /dev/null +++ b/server/descriptor/stfe.json @@ -0,0 +1,18 @@ +[ +    { +        "name": "Test operator", +        "email": "test@example.com", +        "logs": [ +            { +                "max_chain": 3, +                "log_id": "B9oCJk4XIOMXba8dBM5yUj+NLtqTE6xHwbvR9dYkHPM=", +                "signature_schemes": [ +                    2055 +                ], +                "base_url": "example.com/st/v1", +                "signature_scheme": 2055, +                "public_key": "MCowBQYDK2VwAyEAqM4b/SHOCRId9xgiCPn8D8r6+Nrk9JTZZqW6vj7TGa0=" +            } +        ] +    } +] | 
