Skip to content

Commit

Permalink
Added extra validations when loading a saved client
Browse files Browse the repository at this point in the history
  • Loading branch information
daeMOn63 committed Jan 31, 2020
1 parent 227b97e commit 4d1b9ca
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 29 deletions.
13 changes: 13 additions & 0 deletions keys/json.go
Expand Up @@ -72,5 +72,18 @@ func FromRawJSON(raw json.RawMessage) (KeyMaterial, error) {
return nil, err
}

if err := clientKey.validate(); err != nil {
return nil, fmt.Errorf("invalid clientKey: %v", err)
}

// Recompute shared key after unmarshalling the keymaterial
// as this field is not exported
pubKey, ok := clientKey.(*pubKeyMaterial)
if ok {
if err := pubKey.updateSharedKey(); err != nil {
return nil, err
}
}

return clientKey, nil
}
168 changes: 141 additions & 27 deletions keys/json_test.go
Expand Up @@ -16,41 +16,67 @@ package keys

import (
"bytes"
"crypto/ed25519"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"testing"

"golang.org/x/crypto/curve25519"

e4crypto "github.com/teserakt-io/e4go/crypto"
)

var pubKeyJSONTempate = `{
"keyType": %d,
"keyData":{
"PrivateKey":"%s",
"SignerID":"%s",
"C2PubKey":%s,
"PubKeys":{
"%s": "%s"
}
}
}`

var symKeyJSONTemplate = `{
"keyType": %d,
"keyData":{
"Key":"%s"
}
}`

func TestFromRawJSON(t *testing.T) {
t.Run("FromRawJSON properly decode json ed25519 keys", func(t *testing.T) {
privateKey := []byte("privateKey")
signerID := []byte("signerID")
c2PubKey := []byte{}
_, privateKey, err := ed25519.GenerateKey(nil)
if err != nil {
t.Fatalf("Failed to generate private key: %v", err)
}

signerID := e4crypto.HashIDAlias("signerID")
c2PubKey, err := curve25519.X25519(e4crypto.RandomKey(), curve25519.Basepoint)
if err != nil {
t.Fatalf("Failed to generate c2 public key")
}

c2PubKeyStr, err := json.Marshal(c2PubKey)
if err != nil {
t.Fatalf("Failed to encode c2PubKey to string: %v", err)
}

pubKeyID := "pubKeyID1"
pubKeyKey := []byte("pubKeyKey1")

jsonKey := []byte(fmt.Sprintf(`{
"keyType": %d,
"keyData":{
"PrivateKey":"%s",
"SignerID":"%s",
"C2PubKey":%s,
"PubKeys":{
"%s": "%s"
}
}
}`,
pubKeyID := e4crypto.HashIDAlias("pubKeyID1")
pubKeyKey, _, err := ed25519.GenerateKey(nil)
if err != nil {
t.Fatalf("Failed to generate public key: %v", err)
}

jsonKey := []byte(fmt.Sprintf(pubKeyJSONTempate,
pubKeyMaterialType,
base64.StdEncoding.EncodeToString(privateKey),
base64.StdEncoding.EncodeToString(signerID),
c2PubKeyStr,
pubKeyID,
hex.EncodeToString(pubKeyID),
base64.StdEncoding.EncodeToString(pubKeyKey),
))

Expand Down Expand Up @@ -80,7 +106,7 @@ func TestFromRawJSON(t *testing.T) {
t.Fatalf("Invalid pubKey count: got %d, wanted 1", len(typedKey.PubKeys))
}

pk, ok := typedKey.PubKeys[pubKeyID]
pk, ok := typedKey.PubKeys[hex.EncodeToString(pubKeyID)]
if !ok {
t.Fatalf("Expected pubkeys to hold a key for id %s", pubKeyID)
}
Expand All @@ -91,14 +117,9 @@ func TestFromRawJSON(t *testing.T) {
})

t.Run("FromRawJSON properly decode json symmetric keys", func(t *testing.T) {
privateKey := []byte("privateKey")

jsonKey := []byte(fmt.Sprintf(`{
"keyType": %d,
"keyData":{
"Key":"%s"
}
}`,
privateKey := e4crypto.RandomKey()

jsonKey := []byte(fmt.Sprintf(symKeyJSONTemplate,
symKeyMaterialType,
base64.StdEncoding.EncodeToString(privateKey),
))
Expand Down Expand Up @@ -136,4 +157,97 @@ func TestFromRawJSON(t *testing.T) {
}
}
})

t.Run("FromRawJSON properly returns error when loading invalid pubkey data", func(t *testing.T) {
validPrivateKey := e4crypto.RandomKey()
validID := e4crypto.HashIDAlias("random")
validCurvePubKey, err := curve25519.X25519(e4crypto.RandomKey(), curve25519.Basepoint)
if err != nil {
t.Fatalf("Failed to generate c2 pubkey: %v", err)
}
validEdPubKey, _, err := ed25519.GenerateKey(nil)
if err != nil {
t.Fatalf("Failed to generate public key: %v", err)
}

type testData struct {
privateKey []byte
signerID []byte
c2PubKey []byte
pubKeyID []byte
pubKeyKey []byte
}

testDatas := []testData{
{
privateKey: validPrivateKey[1:],
signerID: validID,
c2PubKey: validCurvePubKey,
pubKeyID: validID,
pubKeyKey: validEdPubKey,
},
{
privateKey: validPrivateKey,
signerID: validID[1:],
c2PubKey: validCurvePubKey,
pubKeyID: validID,
pubKeyKey: validEdPubKey,
},
{
privateKey: validPrivateKey,
signerID: validID,
c2PubKey: validCurvePubKey[1:],
pubKeyID: validID,
pubKeyKey: validEdPubKey,
},
{
privateKey: validPrivateKey,
signerID: validID,
c2PubKey: validCurvePubKey,
pubKeyID: validID[1:],
pubKeyKey: validEdPubKey,
},
{
privateKey: validPrivateKey,
signerID: validID,
c2PubKey: validCurvePubKey,
pubKeyID: validID,
pubKeyKey: validEdPubKey[1:],
},
}

for _, testData := range testDatas {

c2PubKeyStr, err := json.Marshal(testData.c2PubKey)
if err != nil {
t.Fatalf("Failed to encode c2PubKey to string: %v", err)
}

jsonKey := []byte(fmt.Sprintf(pubKeyJSONTempate,
pubKeyMaterialType,
base64.StdEncoding.EncodeToString(testData.privateKey),
base64.StdEncoding.EncodeToString(testData.signerID),
c2PubKeyStr,
hex.EncodeToString(testData.pubKeyID),
base64.StdEncoding.EncodeToString(testData.pubKeyKey),
))

_, err = FromRawJSON(jsonKey)
if err == nil {
t.Fatalf("An error was expected while unmarshalling invalid pubkey data %#v", testData)
}
}
})

t.Run("FromRawJSON properly returns error when loading invalid symkey data", func(t *testing.T) {
jsonKey := []byte(fmt.Sprintf(symKeyJSONTemplate,
symKeyMaterialType,
base64.StdEncoding.EncodeToString(e4crypto.RandomKey()[1:]),
))

_, err := FromRawJSON(jsonKey)
if err == nil {
t.Fatal("An error was expected while unmarshalling symkey")
}
})
}
27 changes: 27 additions & 0 deletions keys/publickey.go
Expand Up @@ -305,3 +305,30 @@ func (k *pubKeyMaterial) updateSharedKey() error {

return nil
}

func (k *pubKeyMaterial) validate() error {
if err := e4crypto.ValidateID(k.SignerID); err != nil {
return err
}
if err := e4crypto.ValidateEd25519PrivKey(k.PrivateKey); err != nil {
return err
}
if err := e4crypto.ValidateCurve25519PubKey(k.C2PubKey); err != nil {
return err
}
for id, pubKey := range k.PubKeys {
decodedID, err := hex.DecodeString(id)
if err != nil {
return err
}

if err := e4crypto.ValidateID(decodedID); err != nil {
return err
}
if err := e4crypto.ValidateEd25519PubKey(pubKey); err != nil {
return err
}
}

return nil
}
4 changes: 2 additions & 2 deletions keys/publickey_test.go
Expand Up @@ -399,15 +399,15 @@ func TestPubKeyMaterialMarshalJSON(t *testing.T) {
if err != nil {
t.Fatalf("Failed to generate public key: %v", err)
}
if err := k.AddPubKey([]byte("id1"), pk1); err != nil {
if err := k.AddPubKey(e4crypto.HashIDAlias("id1"), pk1); err != nil {
t.Fatalf("Failed to add pubkey for id1: %v", err)
}

pk2, _, err := ed25519.GenerateKey(nil)
if err != nil {
t.Fatalf("Failed to generate public key: %v", err)
}
if err := k.AddPubKey([]byte("id2"), pk2); err != nil {
if err := k.AddPubKey(e4crypto.HashIDAlias("id2"), pk2); err != nil {
t.Fatalf("Failed to add pubkey for id2: %v", err)
}

Expand Down
4 changes: 4 additions & 0 deletions keys/symmetric.go
Expand Up @@ -104,3 +104,7 @@ func (k *symKeyMaterial) MarshalJSON() ([]byte, error) {

return json.Marshal(jsonKey)
}

func (k *symKeyMaterial) validate() error {
return e4crypto.ValidateSymKey(k.Key)
}
4 changes: 4 additions & 0 deletions keys/types.go
Expand Up @@ -52,6 +52,10 @@ type KeyMaterial interface {
SetKey(key []byte) error
// MarshalJSON marshal the key material into json
MarshalJSON() ([]byte, error)

// validate performs a keyMaterial validation,
// and returns an error when anything is invalid.
validate() error
}

// PubKeyStore interface defines methods to interact with a public key storage
Expand Down

0 comments on commit 4d1b9ca

Please sign in to comment.