From f91f18ea42cad4bbbda6526039c1a2b96d2ab005 Mon Sep 17 00:00:00 2001 From: josh <josh@elixxir.io> Date: Tue, 13 Oct 2020 09:57:04 -0700 Subject: [PATCH] Implement auth key and tests --- diffieHellman/dhkx.go | 3 +- e2e/auth/keygen.go | 48 ++++++++++++++ e2e/auth/keygen_test.go | 136 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 e2e/auth/keygen.go create mode 100644 e2e/auth/keygen_test.go diff --git a/diffieHellman/dhkx.go b/diffieHellman/dhkx.go index e363f5df..dd79319a 100644 --- a/diffieHellman/dhkx.go +++ b/diffieHellman/dhkx.go @@ -12,6 +12,7 @@ import ( "fmt" "gitlab.com/elixxir/crypto/csprng" "gitlab.com/elixxir/crypto/cyclic" + "io" ) const DefaultPrivateKeyLengthBits = 256 @@ -22,7 +23,7 @@ const DefaultPrivateKeyLength = DefaultPrivateKeyLengthBits / 8 // group. It is recommended to use the "DefaultPrivateKeyLength" // for most use cases. // key size must be divisible by 8 -func GeneratePrivateKey(size int, group *cyclic.Group, source csprng.Source) *cyclic.Int { +func GeneratePrivateKey(size int, group *cyclic.Group, source io.Reader) *cyclic.Int { k1, err := csprng.GenerateInGroup(group.GetPBytes(), size, source) diff --git a/e2e/auth/keygen.go b/e2e/auth/keygen.go new file mode 100644 index 00000000..9fc2fdd0 --- /dev/null +++ b/e2e/auth/keygen.go @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the LICENSE file // +//////////////////////////////////////////////////////////////////////////////////////////// +package auth + +import ( + "bytes" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/crypto/cyclic" + dh "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/elixxir/crypto/hash" +) + +const KeygenVector = "MakeAuthKey" + +// MakeAuthKey generates a one-off key to be used to encrypt payloads +// for an authenticated channel +func MakeAuthKey(myPrivKey, partnerPubKey *cyclic.Int, salt []byte, + grp *cyclic.Group) (Key []byte, Vector []byte) { + // Generate the base key for the two users + baseKey := dh.GenerateSessionKey(myPrivKey, partnerPubKey, grp) + + // Generate the hash function + h, err := hash.NewCMixHash() + if err != nil { + jww.FATAL.Panicf("Could not get hash: %+v", err) + } + + // Hash the base key, the salt and the vector together + h.Write(baseKey.Bytes()) + h.Write(salt) + h.Write([]byte(KeygenVector)) + + return h.Sum(nil), []byte(KeygenVector) + +} + +// Verifies that the auth key is valid +func VerifyAuthKey(myPrivKey, partnerPubKey *cyclic.Int, salt []byte, + grp *cyclic.Group, authKey []byte) bool { + + generatedKey, _ := MakeAuthKey(myPrivKey, + partnerPubKey, salt, grp) + + return bytes.Equal(generatedKey, authKey) +} diff --git a/e2e/auth/keygen_test.go b/e2e/auth/keygen_test.go new file mode 100644 index 00000000..3b8fe1f1 --- /dev/null +++ b/e2e/auth/keygen_test.go @@ -0,0 +1,136 @@ +//////////////////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the LICENSE file // +//////////////////////////////////////////////////////////////////////////////////////////// +package auth + +import ( + "encoding/base64" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/elixxir/crypto/large" + "math/rand" + "testing" +) + +func TestMakeAuthKey_Consistency(t *testing.T) { + // Hardcoded expected values + expected := []string{ + "0PSG0GR6/QCcQ+P5+HfGbYyZYrX04SnVuk37tHnFvu0=", + "8CSvWeTn5CujIO07prc1MA1WXueC7FXBP/35JoePyuY=", + "7Wv51EGdOagD8KJNPIZ8Khp3+WHRfyQ3VZHABvnXlRM=", + "QLe72xIwNkiDWZfVW0tuxEode+ZotkZNj9vSPzM0rKQ=", + "GUSK/PWHEmur0eNzMzmAzjLDEXRm3e8qna1XfopmUyo=", + } + + // Initialize a mock salt + salt := []byte("salt") + + // Generate a group + grp := getGrp() + + // Generate a pseudo-rng + prng := rand.New(rand.NewSource(42)) + + // Generate a key for every expected value above + // Check if they match the expected value + for i := 0; i < len(expected); i++ { + // Generate the two keys, public and private + myPrivKey := diffieHellman.GeneratePrivateKey(diffieHellman.DefaultPrivateKeyLength, grp, prng) + partnerPubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(512, grp, prng), grp) + + // Create the auth key + key, _ := MakeAuthKey(myPrivKey, partnerPubKey, salt, grp) + + // Encode the auth key for comparison + key64Encoded := base64.StdEncoding.EncodeToString(key) + + // Check if the key matches the expected value + if expected[i] != key64Encoded { + t.Errorf("received and expected do not match at index %v\n"+ + "\treceived: %s\n\texpected: %s", i, key64Encoded, expected[i]) + } + } + +} + +//Tests that the generated auth keys are verified +func TestMakeAuthKey_Verified(t *testing.T) { + // Set up a number of tests to perform + const numTests = 100 + + // Initialize a mock salt + salt := []byte("salt") + + // Generate a group + grp := getGrp() + + // Generate a pseudo-rng + prng := rand.New(rand.NewSource(42)) + + // Generate and verify a key NUMTESTS times + for i := 0; i < numTests; i++ { + // Generate the two keys, public and private + myPrivKey := diffieHellman.GeneratePrivateKey(diffieHellman.DefaultPrivateKeyLength, grp, prng) + partnerPubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(512, grp, prng), grp) + + // Create the auth key + key, _ := MakeAuthKey(myPrivKey, partnerPubKey, salt, grp) + + // If the auth key cannot be verified, this run fails + if !VerifyAuthKey(myPrivKey, partnerPubKey, salt, grp, key) { + t.Errorf("Auth key could not be verified at index %v", i) + } + } +} + +//Tests that bad proofs are not verified +func TestVerifyOwnershipProof_Bad(t *testing.T) { + // Set up a number of tests to perform + const numTests = 100 + + // Initialize a mock salt + salt := []byte("salt") + + // Generate a group + grp := getGrp() + + // Generate a pseudo-rng + prng := rand.New(rand.NewSource(42)) + + // Generate a bad auth key and check it's not verified + for i := 0; i < numTests; i++ { + // Generate the two keys, public and private + myPrivKey := diffieHellman.GeneratePrivateKey(diffieHellman.DefaultPrivateKeyLength, grp, prng) + partnerPubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(512, grp, prng), grp) + + // Generate a random, non-proper auth key + badKey := make([]byte, 32) + prng.Read(badKey) + + // If this non proper auth key is verified, this run fails + if VerifyAuthKey(myPrivKey, partnerPubKey, salt, grp, badKey) { + t.Errorf("AuthKey was verified at index %v when it is bad", i) + } + + } +} + +// Helper function which generate a group for testing +func getGrp() *cyclic.Group { + primeString := "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" + p := large.NewIntFromString(primeString, 16) + g := large.NewInt(2) + return cyclic.NewGroup(p, g) +} -- GitLab