Skip to content
Snippets Groups Projects
Commit 0b1d6bf8 authored by Jono Wenger's avatar Jono Wenger
Browse files

XX-3029 / Single Use

parent 5c3e52a3
No related branches found
No related tags found
No related merge requests found
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"bytes"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/hash"
)
const macConstant = "macConstant"
// MakeMAC generates the MAC for the given base key and encrypted payload.
func MakeMAC(baseKey *cyclic.Int, encryptedPayload []byte) []byte {
h, err := hash.NewCMixHash()
if err != nil {
jww.ERROR.Panicf("Failed to create hash: %v", err)
}
// Hash the key, number, and constant
h.Write(baseKey.Bytes())
h.Write(encryptedPayload)
h.Write([]byte(macConstant))
return h.Sum(nil)
}
// VerifyMAC determines if the provided MAC is valid for the given base key and
// encrypted payload.
func VerifyMAC(baseKey *cyclic.Int, encryptedPayload, receivedMAC []byte) bool {
newMAC := MakeMAC(baseKey, encryptedPayload)
return bytes.Equal(newMAC, receivedMAC)
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"encoding/base64"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/diffieHellman"
"math/rand"
"testing"
)
// Tests that the generated MACs do not change.
func TestMAC_Consistency(t *testing.T) {
expectedMACs := []string{
"D7vXMT3iX/1tvFPjowoz3w5b3PbECB4EFgkR3hNzyCM=",
"ffW26eqwyTHERUPHbmFkUitRj7c+c/PQayfwQPLihNs=",
"/lyTEnFbzEEmmMjOQhq6qr0jUYE2j22ERcR4CLH9368=",
"vPB8eXP8BXWdxSU4a+Lp1pYVWb98COtWtR0sBngGyTs=",
"BuvhuSO01uM+nVQPwXlOwRzr7xchVM1dRoF9h5TC2HU=",
"vF5iYaFdhLtgOO5hWNpAF6jJaW4utF1MLGaz/gYb0TY=",
"opI2htMJEqZvvEKHAwWnTSqgvaAempY9//rRxNNFHQU=",
"ppGzFglPaLzytF5gJRtSFbYoidsShEBoX1cxkAJY3F4=",
"pdzZmlz6qdChwo7B5sChTRUpQ5zLvlH5LgndOhDHAt8=",
"BHP2yvbUcynr6vM61qt+18YshTsyArJqv0VCq/EI3+o=",
}
grp := getGrp()
prng := rand.New(rand.NewSource(42))
for i, expected := range expectedMACs {
privKey := diffieHellman.GeneratePrivateKey(diffieHellman.DefaultPrivateKeyLength, grp, prng)
pubkey := diffieHellman.GeneratePublicKey(privKey, grp)
baseKey := diffieHellman.GenerateSessionKey(privKey, pubkey, grp)
encryptedPayload := make([]byte, 128)
prng.Read(encryptedPayload)
testMAC := MakeMAC(baseKey, encryptedPayload)
testMACBase64 := base64.StdEncoding.EncodeToString(testMAC)
if expected != testMACBase64 {
t.Errorf("MakeMAC() did not return the expected MAC for the given "+
"base key and encrypted payload at index %d."+
"\nbase key: %s\nexpected: %s\nreceived: %s",
i, baseKey.Text(10), expected, testMACBase64)
}
}
}
// Tests that all generated MACs are unique.
func TestMAC_Unique(t *testing.T) {
grp := getGrp()
prng := rand.New(rand.NewSource(42))
MACs := make(map[string]struct {
key *cyclic.Int
encryptedPayload []byte
}, 100)
for i := 0; i < 100; i++ {
privKey := diffieHellman.GeneratePrivateKey(diffieHellman.DefaultPrivateKeyLength, grp, prng)
pubkey := diffieHellman.GeneratePublicKey(privKey, grp)
baseKey := diffieHellman.GenerateSessionKey(privKey, pubkey, grp)
encryptedPayload := make([]byte, 128)
prng.Read(encryptedPayload)
testMAC := MakeMAC(baseKey, encryptedPayload)
testMACBase64 := base64.StdEncoding.EncodeToString(testMAC)
if _, exists := MACs[testMACBase64]; exists {
t.Errorf("Generated MAC collides with previously generated MAC."+
"\ncurrent MAC: baseKey: %s encryptedPayload: %s"+
"\npreviouse MAC: baseKey: %s encryptedPayload: %s"+
"\nMAC: %s",
baseKey.Text(10),
base64.StdEncoding.EncodeToString(encryptedPayload),
MACs[testMACBase64].key.Text(10),
base64.StdEncoding.EncodeToString(MACs[testMACBase64].encryptedPayload),
base64.StdEncoding.EncodeToString(testMAC))
} else {
MACs[testMACBase64] = struct {
key *cyclic.Int
encryptedPayload []byte
}{baseKey, encryptedPayload}
}
}
}
func TestVerifyMAC(t *testing.T) {
expectedMACs := []string{
"D7vXMT3iX/1tvFPjowoz3w5b3PbECB4EFgkR3hNzyCM=",
"ffW26eqwyTHERUPHbmFkUitRj7c+c/PQayfwQPLihNs=",
"/lyTEnFbzEEmmMjOQhq6qr0jUYE2j22ERcR4CLH9368=",
"vPB8eXP8BXWdxSU4a+Lp1pYVWb98COtWtR0sBngGyTs=",
"BuvhuSO01uM+nVQPwXlOwRzr7xchVM1dRoF9h5TC2HU=",
"vF5iYaFdhLtgOO5hWNpAF6jJaW4utF1MLGaz/gYb0TY=",
"opI2htMJEqZvvEKHAwWnTSqgvaAempY9//rRxNNFHQU=",
"ppGzFglPaLzytF5gJRtSFbYoidsShEBoX1cxkAJY3F4=",
"pdzZmlz6qdChwo7B5sChTRUpQ5zLvlH5LgndOhDHAt8=",
"BHP2yvbUcynr6vM61qt+18YshTsyArJqv0VCq/EI3+o=",
}
grp := getGrp()
prng := rand.New(rand.NewSource(42))
for i, expected := range expectedMACs {
privKey := diffieHellman.GeneratePrivateKey(diffieHellman.DefaultPrivateKeyLength, grp, prng)
pubkey := diffieHellman.GeneratePublicKey(privKey, grp)
baseKey := diffieHellman.GenerateSessionKey(privKey, pubkey, grp)
encryptedPayload := make([]byte, 128)
prng.Read(encryptedPayload)
testMAC := MakeMAC(baseKey, encryptedPayload)
testMACBase64 := base64.StdEncoding.EncodeToString(testMAC)
receivedMac, _ := base64.StdEncoding.DecodeString(expected)
if !VerifyMAC(baseKey, encryptedPayload, receivedMac) {
t.Errorf("VerifyMAC() failed for a correct MAC (%d)."+
"\nbase key: %s\nexpected: %s\nreceived: %s",
i, baseKey.Text(10), expected, testMACBase64)
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"encoding/binary"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/hash"
"gitlab.com/elixxir/primitives/format"
)
const responseFPConstant = "responseFPConstant"
func ResponseFingerprint(pubKey *cyclic.Int, keyNum uint64) format.Fingerprint {
// Create fingerprint
fp := format.Fingerprint{}
copy(fp[:], makeHash(pubKey, keyNum, responseFPConstant))
return fp
}
func makeHash(pubKey *cyclic.Int, keyNum uint64, constant string) []byte {
h, err := hash.NewCMixHash()
if err != nil {
jww.ERROR.Panicf("Failed to create hash: %v", err)
}
// Convert the key number to bytes
buff := make([]byte, binary.MaxVarintLen64)
binary.BigEndian.PutUint64(buff, keyNum)
// Hash the key, number, and constant
h.Write(pubKey.Bytes())
h.Write(buff)
h.Write([]byte(constant))
return h.Sum(nil)
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"encoding/base64"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/diffieHellman"
"math/rand"
"testing"
)
// Tests that the generated fingerprints do not change.
func TestResponseFingerprint(t *testing.T) {
expectedFP := "H+GySzAGq3y6o1JA0Mqxn68GO1uSzCEmpVVbHR2sJc8="
grp := getGrp()
prng := rand.New(rand.NewSource(42))
pubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(
diffieHellman.DefaultPrivateKeyLength, grp, prng), grp)
testFP := ResponseFingerprint(pubKey, 0)
testFPBase64 := base64.StdEncoding.EncodeToString(testFP[:])
if expectedFP != testFPBase64 {
t.Errorf("ResponseFingerprint() did not return the expected "+
"fingerprint for public key %s."+
"\nexpected: %s\nreceived: %s",
pubKey.Text(10), expectedFP, testFPBase64)
}
}
// Tests that the generated fingerprints do not change.
func Test_makeHash_Consistency(t *testing.T) {
expectedHashes := []string{
"R7UL7by0fP2bXRBlzUOrUKo+7pRATF4r6bUD8/H+PBc=",
"CQsWbxgdjYOIJsdfTk/w3549Ltp7TJlSUquK94O8rAM=",
"5+pY4khsqHh0bEXZvYC2DLEJbxq4g5bL19JsllOcfso=",
"FW9gcwJAl90cLcsnxdnHLcIuJO6NpXqkVWFfbXqWXmA=",
"peyTwZZUKPwHB5J1UptEbL+TUEjvg4ZBVceE/J1Q3pQ=",
"f8YCUyFXznRHQ1gzuBJrSQegE7wC1JYb8MPTbtJ+qj0=",
"g6pHsrATAkSl7QMn9Re01nuc5VF88yvyWvPCHKm3upk=",
"S0WrlEhrMIDvJ68hhY6c0Mk5FabZqoAoUdxaBrDXdhg=",
"2mHHoyjQExs314tLMg+6pt1cGE5j4vckWZa18pPjZmQ=",
"2YMO0HeFF6dCd3cKhNQAXw76zaQ573fw0TM/3PLmUGI=",
}
grp := getGrp()
prng := rand.New(rand.NewSource(42))
for i, expectedHash := range expectedHashes {
pubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(
diffieHellman.DefaultPrivateKeyLength, grp, prng), grp)
testHash := makeHash(pubKey, uint64(i), "constant")
testHashBase64 := base64.StdEncoding.EncodeToString(testHash)
if expectedHash != testHashBase64 {
t.Errorf("makeHash() did not return the expected hash for public "+
"key %s at index %d.\nexpected: %s\nreceived: %s",
pubKey.Text(10), i, expectedHash, testHashBase64)
}
}
}
// Tests that all generated fingerprints are unique.
func Test_makeHash_Unique(t *testing.T) {
grp := getGrp()
prng := rand.New(rand.NewSource(42))
hashes := make(map[string]*cyclic.Int, 100)
for i := 0; i < 100; i++ {
pubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(
diffieHellman.DefaultPrivateKeyLength, grp, prng), grp)
testHash := makeHash(pubKey, uint64(i), "constant")
hashBase64 := base64.StdEncoding.EncodeToString(testHash)
if hashes[hashBase64] != nil {
t.Errorf("Generated hash from key %s collides with "+
"previously generated hash from key %s.\nfingerprint: %s",
pubKey.Text(10), hashes[hashBase64].Text(10), hashBase64)
} else {
hashes[hashBase64] = pubKey
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"gitlab.com/elixxir/crypto/cyclic"
)
const responseKeyConstant = "responseKeyConstant"
func ResponseKey(pubKey *cyclic.Int, keyNum uint64) []byte {
return makeHash(pubKey, keyNum, responseKeyConstant)
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"encoding/base64"
"gitlab.com/elixxir/crypto/diffieHellman"
"math/rand"
"testing"
)
// Tests that the generated key does not change.
func TestResponseKey(t *testing.T) {
expectedKey := "6H61xTtJZYhmT8Q2cm3ZXj7J95yHO5lQN/s1cRu/j40="
grp := getGrp()
prng := rand.New(rand.NewSource(42))
pubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(
diffieHellman.DefaultPrivateKeyLength, grp, prng), grp)
testKey := ResponseKey(pubKey, 0)
testKeyBase64 := base64.StdEncoding.EncodeToString(testKey)
if expectedKey != testKeyBase64 {
t.Errorf("ResponseKey() did not return the expected key for public "+
"key %s.\nexpected: %s\nreceived: %s",
pubKey.Text(10), expectedKey, testKeyBase64)
}
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package singleUse
import (
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/hash"
"gitlab.com/elixxir/primitives/format"
)
const transmitFPConstant = "transmitFPConstant"
func TransmitFingerprint(pubKey *cyclic.Int) format.Fingerprint {
// Create new hash
h, err := hash.NewCMixHash()
if err != nil {
jww.ERROR.Panicf("Failed to create hash: %v", err)
}
// Hash the key and constant
h.Write(pubKey.Bytes())
h.Write([]byte(transmitFPConstant))
keyHash := h.Sum(nil)
// Create fingerprint
fp := format.Fingerprint{}
copy(fp[:], keyHash)
return fp
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package singleUse
import (
"encoding/base64"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/diffieHellman"
"gitlab.com/elixxir/primitives/format"
"gitlab.com/xx_network/crypto/large"
"math/rand"
"testing"
)
// Tests that the generated fingerprints do not change.
func TestTransmitFingerprint_Consistency(t *testing.T) {
expectedFPs := []string{
"8xef7y86YmR6+qVBaVghPYbEd0j7seLUxR1v1dxqiNo=",
"LJ1HQ8zZPY3z+6UkKZMSDN2WymMmwuWW3GCjtAGfUlc=",
"Fc8CN69uMxT1zBAr3Ed/AOy6Py3XDb3i7LngRsax0K8=",
"4mvA+dxgIy/UxRVIvzFgGtEuMoWI8RodF7JMFIO5xcI=",
"3YJPhLeI2+RawlSMUTEwTP1iJrFAa5zboCf5fjc/k3o=",
"mEOS0pDuNYS5hpNHeJ2IhzlZFf9J5oHRvFpovNwWS7c=",
"i3k7dv1Nch1oTT4aOxbBDifmf7+mT34ErFFaWW5LDb8=",
"ck/wkZ3lv0bcQuW+Z2dw37m+Re0URPw4UsWBPAWBEtw=",
"k/YRXaE2dplVPZSiEY+7C0e6GlDeR3jLrIPRWgeL3cI=",
"qkT2Hfz8A7jNxOhDYG266b/hvWcQtAx0ay67Az80bAY=",
}
grp := getGrp()
prng := rand.New(rand.NewSource(42))
for i, expected := range expectedFPs {
pubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(
diffieHellman.DefaultPrivateKeyLength, grp, prng), grp)
testFP := TransmitFingerprint(pubKey)
testFPBase64 := base64.StdEncoding.EncodeToString(testFP[:])
if expected != testFPBase64 {
t.Errorf("TransmitFingerprint() did not return the expected "+
"fingerprint for public key %s at index %d."+
"\nexpected: %s\nreceived: %s",
pubKey.Text(10), i, expected, testFPBase64)
}
}
}
// Tests that all generated fingerprints are unique.
func TestTransmitFingerprint_Unique(t *testing.T) {
grp := getGrp()
prng := rand.New(rand.NewSource(42))
FPs := make(map[format.Fingerprint]*cyclic.Int, 100)
for i := 0; i < 100; i++ {
pubKey := diffieHellman.GeneratePublicKey(diffieHellman.GeneratePrivateKey(
diffieHellman.DefaultPrivateKeyLength, grp, prng), grp)
testFP := TransmitFingerprint(pubKey)
if FPs[testFP] != nil {
t.Errorf("Generated fingerprint from key %s collides with "+
"previously generated fingerprint from key %s."+
"\nfingerprint: %s", pubKey.Text(10), FPs[testFP].Text(10),
base64.StdEncoding.EncodeToString(testFP[:]))
} else {
FPs[testFP] = pubKey
}
}
}
func getGrp() *cyclic.Group {
primeString := "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" +
"A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1" +
"4374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDE" +
"E386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA4" +
"8361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077" +
"096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E8" +
"6039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE51" +
"5D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"
p := large.NewIntFromString(primeString, 16)
g := large.NewInt(2)
return cyclic.NewGroup(p, g)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment