Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scrpto: Move KeyMeta + Version #2912

Merged
merged 3 commits into from
Jul 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go/lib/scrypto/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ go_library(
srcs = [
"asym.go",
"defs.go",
"keymeta.go",
"mac.go",
"rand.go",
"validity.go",
"version.go",
],
importpath = "github.com/scionproto/scion/go/lib/scrypto",
visibility = ["//visibility:public"],
Expand All @@ -24,8 +26,10 @@ go_test(
name = "go_default_test",
srcs = [
"asym_test.go",
"keymeta_test.go",
"rand_test.go",
"validity_test.go",
"version_test.go",
],
embed = [":go_default_library"],
deps = [
Expand Down
83 changes: 83 additions & 0 deletions go/lib/scrypto/keymeta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2019 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package scrypto

import (
"bytes"
"encoding/json"
"errors"

"github.com/scionproto/scion/go/lib/common"
)

var (
// ErrKeyVersionNotSet indicates KeyVersion is not set.
ErrKeyVersionNotSet = errors.New("key version not set")
// ErrAlgorithmNotSet indicates the key algorithm is not set.
ErrAlgorithmNotSet = errors.New("algorithm not set")
// ErrKeyNotSet indicates the key is not set.
ErrKeyNotSet = errors.New("key not set")
)

// KeyMeta holds the raw key with metadata.
type KeyMeta struct {
// KeyVersion identifies the key. It must change if the key changes, and
// stay the same if the key does not change.
KeyVersion KeyVersion `json:"KeyVersion"`
// Algorithm indicates the algorithm associated with the key.
Algorithm string `json:"Algorithm"`
// Key is the raw public key.
Key common.RawBytes `json:"Key"`
}

// UnmarshalJSON checks that all fields are set.
func (m *KeyMeta) UnmarshalJSON(b []byte) error {
var alias keyMetaAlias
dec := json.NewDecoder(bytes.NewReader(b))
dec.DisallowUnknownFields()
if err := dec.Decode(&alias); err != nil {
return err
}
if err := alias.checkAllSet(); err != nil {
return err
}
*m = KeyMeta{
KeyVersion: *alias.KeyVersion,
Algorithm: *alias.Algorithm,
Key: *alias.Key,
}
return nil
}

type keyMetaAlias struct {
KeyVersion *KeyVersion `json:"KeyVersion"`
Algorithm *string `json:"Algorithm"`
Key *common.RawBytes `json:"Key"`
}

func (m *keyMetaAlias) checkAllSet() error {
switch {
case m.KeyVersion == nil:
return ErrKeyVersionNotSet
case m.Algorithm == nil:
return ErrAlgorithmNotSet
case m.Key == nil:
return ErrKeyNotSet
}
return nil
}

// KeyVersion identifies a key version.
type KeyVersion uint64
100 changes: 100 additions & 0 deletions go/lib/scrypto/keymeta_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2019 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package scrypto_test

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/scionproto/scion/go/lib/scrypto"
"github.com/scionproto/scion/go/lib/xtest"
)

func TestKeyMetaUnmarshalJSON(t *testing.T) {
tests := map[string]struct {
Input string
Meta scrypto.KeyMeta
ExpectedErrMsg string
}{
"Valid": {
Input: `
{
"KeyVersion": 1,
"Algorithm": "ed25519",
"Key": "YW5hcGF5YSDinaQgIHNjaW9u"
}`,
Meta: scrypto.KeyMeta{
KeyVersion: 1,
Algorithm: scrypto.Ed25519,
Key: xtest.MustParseHexString("616e617061796120e29da420207363696f6e"),
},
},
"KeyVersion not set": {
Input: `
{
"Algorithm": "ed25519",
"Key": "YW5hcGF5YSDinaQgIHNjaW9u"
}`,
ExpectedErrMsg: scrypto.ErrKeyVersionNotSet.Error(),
},
"Algorithm not set": {
Input: `
{
"KeyVersion": 1,
"Key": "YW5hcGF5YSDinaQgIHNjaW9u"
}`,
ExpectedErrMsg: scrypto.ErrAlgorithmNotSet.Error(),
},
"Key not set": {
Input: `
{
"KeyVersion": 1,
"Algorithm": "ed25519"
}`,
ExpectedErrMsg: scrypto.ErrKeyNotSet.Error(),
},
"Unknown field": {
Input: `
{
"UnknownField": "UNKNOWN"
}`,
ExpectedErrMsg: `json: unknown field "UnknownField"`,
},
"invalid json": {
Input: `
{
"KeyVersion": 1,
"Algorithm": "ed25519"
`,
ExpectedErrMsg: "unexpected end of JSON input",
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
var meta scrypto.KeyMeta
err := json.Unmarshal([]byte(test.Input), &meta)
if test.ExpectedErrMsg == "" {
require.NoError(t, err)
assert.Equal(t, test.Meta, meta)
} else {
require.Error(t, err)
assert.Contains(t, err.Error(), test.ExpectedErrMsg)
}
})
}
}
5 changes: 3 additions & 2 deletions go/lib/scrypto/trc/v2/keychanges.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/scrypto"
)

const (
Expand All @@ -29,7 +30,7 @@ const (
)

// ASToKeyMeta maps an AS to its key metadata for a single key type.
type ASToKeyMeta map[addr.AS]KeyMeta
type ASToKeyMeta map[addr.AS]scrypto.KeyMeta

// KeyChanges contains all new keys in a TRC update.
type KeyChanges struct {
Expand Down Expand Up @@ -81,7 +82,7 @@ func (c *KeyChanges) insertModifications(as addr.AS, prev, next PrimaryAS) error
// If the algorithm and key are not modified by the update, the version must not
// change. If they are modified, the version must be increased by one. The
// return value indicates, whether the update is a modification.
func ValidateKeyUpdate(prev, next KeyMeta) (bool, error) {
func ValidateKeyUpdate(prev, next scrypto.KeyMeta) (bool, error) {
modified := next.Algorithm != prev.Algorithm || !bytes.Equal(next.Key, prev.Key)
switch {
case modified && next.KeyVersion != prev.KeyVersion+1:
Expand Down
3 changes: 2 additions & 1 deletion go/lib/scrypto/trc/v2/pop.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package trc
import (
"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/scrypto"
)

const (
Expand Down Expand Up @@ -69,7 +70,7 @@ func (v *popValidator) popForModType(changes map[KeyType]ASToKeyMeta) error {
return nil
}

func (v *popValidator) popForKeyType(keyType KeyType, m map[addr.AS]KeyMeta) error {
func (v *popValidator) popForKeyType(keyType KeyType, m map[addr.AS]scrypto.KeyMeta) error {
for as := range m {
if !v.hasPop(v.TRC.ProofOfPossession[as], keyType) {
return common.NewBasicError(MissingProofOfPossession, nil, "AS", as, "keyType", keyType)
Expand Down
62 changes: 3 additions & 59 deletions go/lib/scrypto/trc/v2/primary.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/scrypto"
)

// Parsing errors with context.
Expand Down Expand Up @@ -57,11 +58,6 @@ var (
ErrAttributesNotSet = errors.New("attributes not set")
// ErrKeysNotSet indicates the keys in a primary AS are not set.
ErrKeysNotSet = errors.New("keys not set")

// ErrAlgorithmNotSet indicates the key algorithm is not set.
ErrAlgorithmNotSet = errors.New("algorithm not set")
// ErrKeyNotSet indicates the key is not set.
ErrKeyNotSet = errors.New("key not set")
)

// PrimaryASes holds all primary ASes and maps them to their attributes and keys.
Expand Down Expand Up @@ -104,8 +100,8 @@ type primaryASAlias PrimaryAS

// PrimaryAS holds the attributes and keys of a primary AS.
type PrimaryAS struct {
Attributes Attributes `json:"Attributes"`
Keys map[KeyType]KeyMeta `json:"Keys"`
Attributes Attributes `json:"Attributes"`
Keys map[KeyType]scrypto.KeyMeta `json:"Keys"`
}

// Is returns true if the primary AS holds this property.
Expand Down Expand Up @@ -167,58 +163,6 @@ func (p *PrimaryAS) checkAllSet() error {
return nil
}

// KeyMeta holds the key with metadata. TODO(roosd): rename to key. Inspect all
// occurrences of trc.Key in the codebase, as they are different things.
type KeyMeta struct {
// KeyVersion identifies the key. It must change if the key changes, and
// stay the same if the key does not change.
KeyVersion KeyVersion `json:"KeyVersion"`
// Algorithm indicates the algorithm associated with the key.
Algorithm string `json:"Algorithm"`
// Key is the raw public key.
Key common.RawBytes `json:"Key"`
}

// UnmarshalJSON checks that all fields are set.
func (m *KeyMeta) UnmarshalJSON(b []byte) error {
var alias keyMetaAlias
dec := json.NewDecoder(bytes.NewReader(b))
dec.DisallowUnknownFields()
if err := dec.Decode(&alias); err != nil {
return err
}
if err := alias.checkAllSet(); err != nil {
return err
}
*m = KeyMeta{
KeyVersion: *alias.KeyVersion,
Algorithm: *alias.Algorithm,
Key: *alias.Key,
}
return nil
}

type keyMetaAlias struct {
KeyVersion *KeyVersion `json:"KeyVersion"`
Algorithm *string `json:"Algorithm"`
Key *common.RawBytes `json:"Key"`
}

func (m *keyMetaAlias) checkAllSet() error {
switch {
case m.KeyVersion == nil:
return ErrKeyVersionNotSet
case m.Algorithm == nil:
return ErrAlgorithmNotSet
case m.Key == nil:
return ErrKeyNotSet
}
return nil
}

// KeyVersion identifies a key for a given KeyType and ISD-AS.
type KeyVersion uint64

var _ json.Marshaler = (*Attributes)(nil)
var _ json.Unmarshaler = (*Attributes)(nil)

Expand Down
Loading