satellite/orders: add encryption keys
This adds EncryptionKey definition that can be used as a flag. These order.EncryptionKey-s will be used to encrypt data in order limits. This helps to avoid storing lots of transient data in the main database. This code doesn't yet contain encryption itself. Change-Id: I2efae102a89b851d33342a0106f8d8b3f35119bb
This commit is contained in:
parent
9b90712aa0
commit
735dc6e163
148
satellite/orders/encryptionkey.go
Normal file
148
satellite/orders/encryptionkey.go
Normal file
@ -0,0 +1,148 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package orders
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/common/storj"
|
||||
)
|
||||
|
||||
// ErrEncryptionKey is error class used for keys.
|
||||
var ErrEncryptionKey = errs.Class("order encryption key")
|
||||
|
||||
// EncryptionKeyID is used to identify an encryption key.
|
||||
type EncryptionKeyID [8]byte
|
||||
|
||||
// IsZero returns whether the key contains no data.
|
||||
func (key EncryptionKeyID) IsZero() bool { return key == EncryptionKeyID{} }
|
||||
|
||||
// EncryptionKeys contains a collection of keys.
|
||||
//
|
||||
// Can be used as a flag.
|
||||
type EncryptionKeys struct {
|
||||
Default EncryptionKey
|
||||
List []EncryptionKey
|
||||
KeyByID map[EncryptionKeyID]storj.Key
|
||||
}
|
||||
|
||||
// EncryptionKey contains an identifier and an encryption key that is used to
|
||||
// encrypt transient metadata in orders.
|
||||
//
|
||||
// Can be used as a flag.
|
||||
type EncryptionKey struct {
|
||||
ID EncryptionKeyID
|
||||
Key storj.Key
|
||||
}
|
||||
|
||||
// IsZero returns whether they key contains some data.
|
||||
func (key *EncryptionKey) IsZero() bool {
|
||||
return key.ID.IsZero() || key.Key.IsZero()
|
||||
}
|
||||
|
||||
// Type implements pflag.Value.
|
||||
func (EncryptionKey) Type() string { return "orders.EncryptionKey" }
|
||||
|
||||
// String is required for pflag.Value.
|
||||
func (key *EncryptionKey) String() string {
|
||||
return hex.EncodeToString(key.ID[:]) + "=" + hex.EncodeToString(key.Key[:])
|
||||
}
|
||||
|
||||
// Set sets the value from an hex encoded string "hex(id)=hex(key)".
|
||||
func (key *EncryptionKey) Set(s string) error {
|
||||
tokens := strings.SplitN(s, "=", 2)
|
||||
if len(tokens) != 2 {
|
||||
return ErrEncryptionKey.New("invalid definition %q", s)
|
||||
}
|
||||
|
||||
err := setHexEncodedArray(key.ID[:], tokens[0])
|
||||
if err != nil {
|
||||
return ErrEncryptionKey.New("invalid id %q: %v", tokens[0], err)
|
||||
}
|
||||
|
||||
err = setHexEncodedArray(key.Key[:], tokens[1])
|
||||
if err != nil {
|
||||
return ErrEncryptionKey.New("invalid key %q: %v", tokens[1], err)
|
||||
}
|
||||
|
||||
if key.ID.IsZero() || key.Key.IsZero() {
|
||||
return ErrEncryptionKey.New("neither identifier or key can be zero")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type implements pflag.Value.
|
||||
func (EncryptionKeys) Type() string { return "orders.EncryptionKeys" }
|
||||
|
||||
// Set adds the values from a comma delimited hex encoded strings "hex(id1)=hex(key1),hex(id2)=hex(key2)".
|
||||
func (keys *EncryptionKeys) Set(s string) error {
|
||||
if keys.KeyByID == nil {
|
||||
keys.KeyByID = map[EncryptionKeyID]storj.Key{}
|
||||
}
|
||||
|
||||
for _, x := range strings.Split(s, ",") {
|
||||
x = strings.TrimSpace(x)
|
||||
var ekey EncryptionKey
|
||||
if err := ekey.Set(x); err != nil {
|
||||
return ErrEncryptionKey.New("invalid keys %q: %v", s, err)
|
||||
}
|
||||
if ekey.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
if keys.Default.IsZero() {
|
||||
keys.Default = ekey
|
||||
}
|
||||
|
||||
if _, exists := keys.KeyByID[ekey.ID]; exists {
|
||||
return ErrEncryptionKey.New("duplicate key identifier %q", s)
|
||||
}
|
||||
|
||||
keys.List = append(keys.List, ekey)
|
||||
keys.KeyByID[ekey.ID] = ekey.Key
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String is required for pflag.Value.
|
||||
func (keys *EncryptionKeys) String() string {
|
||||
var s strings.Builder
|
||||
if keys.Default.IsZero() {
|
||||
return ""
|
||||
}
|
||||
|
||||
s.WriteString(keys.Default.String())
|
||||
for _, key := range keys.List {
|
||||
if key.ID == keys.Default.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
s.WriteString(",")
|
||||
s.WriteString(key.String())
|
||||
}
|
||||
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// setHexEncodedArray sets dst bytes to hex decoded s, verify that the result matches dst.
|
||||
func setHexEncodedArray(dst []byte, s string) error {
|
||||
s = strings.TrimSpace(s)
|
||||
if len(s) != len(dst)*2 {
|
||||
return fmt.Errorf("wrong hex length %d, expected %d", len(s), len(dst)*2)
|
||||
}
|
||||
|
||||
bytes, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
copy(dst, bytes)
|
||||
return nil
|
||||
}
|
137
satellite/orders/encryptionkey_test.go
Normal file
137
satellite/orders/encryptionkey_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package orders_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"storj.io/common/storj"
|
||||
"storj.io/storj/satellite/orders"
|
||||
)
|
||||
|
||||
func TestEncryptionKey_Set_Valid(t *testing.T) {
|
||||
type Test struct {
|
||||
Hex string
|
||||
Key orders.EncryptionKey
|
||||
}
|
||||
|
||||
tests := []Test{
|
||||
{
|
||||
Hex: `0100000000000000=0100000000000000000000000000000000000000000000000000000000000000`,
|
||||
Key: orders.EncryptionKey{
|
||||
ID: orders.EncryptionKeyID{0x01},
|
||||
Key: storj.Key{0x01},
|
||||
},
|
||||
},
|
||||
{
|
||||
Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF`,
|
||||
Key: orders.EncryptionKey{
|
||||
ID: orders.EncryptionKeyID{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xFF},
|
||||
Key: storj.Key{
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xFF,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var got orders.EncryptionKey
|
||||
|
||||
err := got.Set(test.Hex)
|
||||
assert.NoError(t, err, test.Hex)
|
||||
assert.Equal(t, test.Key, got, test.Hex)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptionKey_Set_Invalid(t *testing.T) {
|
||||
type Test struct {
|
||||
Hex string
|
||||
}
|
||||
|
||||
tests := []Test{
|
||||
{Hex: ``},
|
||||
{Hex: `=`},
|
||||
{Hex: `01=`},
|
||||
{Hex: `=01`},
|
||||
{Hex: `1=1`},
|
||||
|
||||
{Hex: `=1122334455667788112233445566778811223344556677881122334455667788`},
|
||||
{Hex: `112233445566778=1122334455667788112233445566778811223344556677881122334455667788`},
|
||||
|
||||
{Hex: `1122334455667788=`},
|
||||
{Hex: `1122334455667788=112233445566778811223344556677881122334455667788112233445566778`},
|
||||
|
||||
{Hex: `11223344556677QQ=11223344556677881122334455667788112233445566778811223344556677QQ`},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var got orders.EncryptionKey
|
||||
|
||||
err := got.Set(test.Hex)
|
||||
assert.Error(t, err, test.Hex)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptionKeys_Set_Valid(t *testing.T) {
|
||||
var keys orders.EncryptionKeys
|
||||
|
||||
err := keys.Set(`11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,0100000000000000=0100000000000000000000000000000000000000000000000000000000000000`)
|
||||
require.NoError(t, err)
|
||||
|
||||
first := orders.EncryptionKey{
|
||||
ID: orders.EncryptionKeyID{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xFF},
|
||||
Key: storj.Key{
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xFF,
|
||||
},
|
||||
}
|
||||
second := orders.EncryptionKey{
|
||||
ID: orders.EncryptionKeyID{0x01},
|
||||
Key: storj.Key{0x01},
|
||||
}
|
||||
|
||||
assert.Equal(t, first, keys.Default)
|
||||
assert.EqualValues(t, []orders.EncryptionKey{first, second}, keys.List)
|
||||
|
||||
assert.Equal(t, first.Key, keys.KeyByID[first.ID])
|
||||
assert.Equal(t, second.Key, keys.KeyByID[second.ID])
|
||||
}
|
||||
|
||||
func TestEncryptionKeys_Set_Invalid(t *testing.T) {
|
||||
type Test struct {
|
||||
Hex string
|
||||
}
|
||||
|
||||
tests := []Test{
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,=`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,01=`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,=01`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,1=1`},
|
||||
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,=1122334455667788112233445566778811223344556677881122334455667788`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,112233445566778=1122334455667788112233445566778811223344556677881122334455667788`},
|
||||
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,1122334455667788=`},
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,1122334455667788=112233445566778811223344556677881122334455667788112233445566778`},
|
||||
|
||||
{Hex: `11223344556677FF=11223344556677881122334455667788112233445566778811223344556677FF,11223344556677QQ=11223344556677881122334455667788112233445566778811223344556677QQ`},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var got orders.EncryptionKeys
|
||||
|
||||
err := got.Set(test.Hex)
|
||||
assert.Error(t, err, test.Hex)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user