diff --git a/e2e/auth/crypt.go b/e2e/auth/crypt.go index c2d8c8f6cc2ada5ff2698420326466952de0b0ff..7d391256ce52f37ae536b8de74d6f07c6c809efe 100644 --- a/e2e/auth/crypt.go +++ b/e2e/auth/crypt.go @@ -8,27 +8,23 @@ package auth import ( jww "github.com/spf13/jwalterweatherman" - "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/salsa20" ) -// Required length of the nonce within XChaCha20 -const NonceLength = chacha20.NonceSizeX +// Required length of the nonce within Salsa20 +const NonceLength = 24 -// Crypt XChaCha20 encrypts or decrypts a message with the passed key and vector +// Crypt Salsa20 encrypts or decrypts a message with the passed key and vector func Crypt(key, vector, msg []byte) (crypt []byte) { - // Bound check that the vector is long enough for XChaCha20 encryption/decryption + // Bound check that the vector is long enough for Salsa20 encryption/decryption if len(vector) < NonceLength { jww.ERROR.Panicf("Vector is not of sufficient length for encryption/decryption") } out := make([]byte, len(msg)) - nonce := vector[:NonceLength] - - cipher, err := chacha20.NewUnauthenticatedCipher(key[:], nonce) - if err != nil { - panic(err) - } - cipher.XORKeyStream(out, msg) + var keyArray [32]byte + copy(keyArray[:], key) + salsa20.XORKeyStream(out, msg, vector[:NonceLength], &keyArray) // Return the result return out diff --git a/e2e/auth/crypt_test.go b/e2e/auth/crypt_test.go index eb886169c72138dd0984752eee12998c1cc22a87..94f7b979902155bbf9965b3450500892674d818b 100644 --- a/e2e/auth/crypt_test.go +++ b/e2e/auth/crypt_test.go @@ -51,10 +51,10 @@ func TestEncrypt_Consistency(t *testing.T) { const messageSize = 100 // Set up expected values with base64 encoding expectedMsgs := [][]byte{ - {0xfa, 0xb, 0x9e, 0x56, 0x87, 0x28, 0x9, 0x3c, 0xe3, 0xc1, 0xe, 0x31, 0xda, 0x46, 0x7, 0x47, 0xea, 0x2d, 0x2a, 0x9a, 0x27, 0xd1, 0x3e, 0xcd, 0x22, 0xf5, 0x20, 0xac, 0x2e, 0x16, 0x4c, 0x1d, 0xf8, 0xb1, 0x52, 0x6f, 0xda, 0x6b, 0x3, 0xf9, 0xfb, 0x29, 0xe7, 0x4f, 0x73, 0x55, 0x9c, 0x42, 0x93, 0xd4, 0x78, 0x97, 0xc1, 0xd6, 0xc5, 0x26, 0xf1, 0x41, 0x7c, 0xbb, 0xc6, 0xfc, 0xcd, 0x8e, 0x9e, 0x1c, 0xd5, 0x4d, 0x46, 0xfe, 0x9d, 0x9, 0xf7, 0x1c, 0xc8, 0x55, 0x33, 0xf1, 0x75, 0xa6, 0x28, 0xe4, 0xd2, 0x3, 0x4b, 0xb9, 0x1d, 0xe1, 0xba, 0xd3, 0x48, 0x31, 0x56, 0xbf, 0x71, 0xa1, 0x98, 0x6, 0x9e, 0xd4}, - {0xff, 0x16, 0xb7, 0x2a, 0xb, 0x78, 0x6b, 0x29, 0x2a, 0x13, 0x3a, 0xe2, 0x88, 0x49, 0xf1, 0xf4, 0xf5, 0x24, 0xc9, 0xea, 0x61, 0x8b, 0x40, 0x25, 0x5a, 0x17, 0x91, 0xbb, 0x9f, 0xb5, 0x5f, 0xff, 0x24, 0x5d, 0x4d, 0xd5, 0x6c, 0x84, 0x54, 0x7d, 0xb0, 0xbc, 0x54, 0x4, 0xfc, 0xfe, 0x5e, 0xae, 0x7f, 0x18, 0xc4, 0x82, 0x69, 0xa8, 0x78, 0x3e, 0x14, 0x6b, 0xa2, 0xd5, 0xac, 0x61, 0xb1, 0x9d, 0x68, 0xfa, 0x5d, 0x78, 0x20, 0xb6, 0x7c, 0x14, 0x65, 0x73, 0x6b, 0xaf, 0xea, 0xb8, 0x4d, 0xd1, 0x6, 0xf9, 0x1d, 0xf9, 0xe6, 0x65, 0xb6, 0x41, 0xe, 0x98, 0x22, 0x38, 0x1d, 0x77, 0xcd, 0xd7, 0x9c, 0xc9, 0xb8, 0x51}, - {0x2d, 0x30, 0xc4, 0x41, 0xd7, 0xb8, 0x21, 0x2, 0x9e, 0xe2, 0xee, 0x71, 0x81, 0x88, 0xbd, 0x55, 0x9c, 0x11, 0xc7, 0x47, 0x1, 0x4, 0x5a, 0x1a, 0xab, 0x13, 0xa4, 0x4b, 0xb8, 0xc1, 0x89, 0xde, 0x73, 0x6f, 0x9f, 0xae, 0x7b, 0xd7, 0xb, 0xc2, 0x74, 0x6c, 0xc3, 0x28, 0x2c, 0xeb, 0xa9, 0x58, 0x3a, 0x22, 0x41, 0xf7, 0xd4, 0x66, 0xf2, 0x90, 0x86, 0x15, 0xb2, 0x6, 0xa1, 0xc7, 0x90, 0x27, 0xb3, 0x1b, 0x6d, 0x85, 0x5a, 0xd6, 0x92, 0x74, 0x66, 0x56, 0x1, 0x68, 0x69, 0xd6, 0xc5, 0x3, 0xc7, 0x47, 0xa3, 0x4, 0x2f, 0x8, 0x22, 0xc0, 0x62, 0xbe, 0x2f, 0x88, 0xdd, 0x56, 0xc3, 0x8f, 0xb9, 0x4a, 0xb8, 0x3e}, - {0x66, 0xef, 0xc, 0x37, 0x6f, 0x57, 0x79, 0x88, 0x66, 0x5b, 0x39, 0x7e, 0xa4, 0xa4, 0xc0, 0x30, 0x9c, 0x81, 0x8, 0x8a, 0xa8, 0x84, 0x6d, 0x74, 0x32, 0x5f, 0x87, 0xd4, 0xb0, 0x7, 0x27, 0x61, 0x9f, 0x91, 0x7f, 0x12, 0x4d, 0x3b, 0x85, 0xda, 0xc0, 0xbb, 0xd4, 0x26, 0xec, 0x75, 0x63, 0xc2, 0x63, 0xa0, 0xf9, 0x6c, 0xff, 0xb3, 0xed, 0xe4, 0x91, 0xcd, 0xbb, 0x5e, 0x32, 0x25, 0x69, 0x24, 0xd3, 0xaa, 0xa3, 0x2a, 0x3, 0x67, 0x35, 0xf2, 0xa3, 0xd6, 0x18, 0x37, 0xce, 0xce, 0xd0, 0x78, 0x60, 0x68, 0x16, 0x12, 0x4b, 0xa0, 0x0, 0x3c, 0x60, 0x7e, 0x4, 0xac, 0xac, 0x14, 0xce, 0xdc, 0x21, 0x3d, 0xfd, 0x6d}, + {0x50, 0x65, 0x42, 0x78, 0x99, 0x23, 0x76, 0x96, 0x78, 0x89, 0x51, 0xec, 0xe0, 0x36, 0x89, 0x9, 0x94, 0x87, 0x31, 0x2d, 0x1b, 0xb3, 0x97, 0xe9, 0x17, 0xd9, 0x9b, 0xf1, 0x90, 0x64, 0x6a, 0xdf, 0xa8, 0xfe, 0x65, 0x17, 0x7b, 0x52, 0x42, 0x44, 0x16, 0xe0, 0x17, 0x46, 0x7a, 0xc2, 0x17, 0x32, 0xde, 0x6d, 0xf3, 0x78, 0x16, 0x29, 0xe3, 0xf4, 0xe0, 0x76, 0xdd, 0xe1, 0x85, 0x2b, 0x2c, 0xc4, 0xe3, 0x67, 0x74, 0xaa, 0xde, 0x97, 0xf5, 0xe4, 0x7e, 0x2d, 0x3c, 0xfe, 0x57, 0xd3, 0x64, 0xd2, 0xea, 0x6f, 0x30, 0xf0, 0xff, 0x8d, 0x92, 0xa, 0xcb, 0x35, 0x4a, 0xae, 0x52, 0xfd, 0x4, 0xfa, 0xf, 0x7a, 0x2c, 0x88}, + {0x4f, 0xf9, 0x31, 0xd8, 0x6b, 0xa, 0x3a, 0x6b, 0x79, 0x80, 0x13, 0xc3, 0x98, 0xc9, 0x96, 0x7c, 0x7c, 0xde, 0xe0, 0x1c, 0x34, 0x56, 0x5b, 0x9a, 0xe2, 0x27, 0x9, 0x18, 0x82, 0xc0, 0x0, 0x32, 0xc7, 0xeb, 0xda, 0xf6, 0xc, 0x7f, 0x17, 0xaf, 0x43, 0x94, 0xc8, 0xbd, 0x78, 0x71, 0x37, 0xd6, 0xb, 0x71, 0x77, 0x26, 0x8f, 0xaf, 0x72, 0x87, 0x39, 0x83, 0xd1, 0xa4, 0xf3, 0xce, 0x15, 0x2f, 0xf6, 0xa4, 0xb9, 0xaf, 0xd3, 0xc7, 0xce, 0xc4, 0x83, 0x75, 0xea, 0x14, 0x17, 0x15, 0x9e, 0x2b, 0xbd, 0xf0, 0x7d, 0x2d, 0xdf, 0x6, 0x93, 0xb7, 0xb4, 0x27, 0x42, 0x4, 0xc3, 0xc1, 0x8b, 0xb3, 0xdf, 0x2d, 0x8, 0xea}, + {0xe0, 0xf6, 0xfc, 0xac, 0xc9, 0xf9, 0xd3, 0x24, 0x74, 0xa6, 0x97, 0x7a, 0x66, 0xc8, 0xcb, 0xe8, 0x27, 0x43, 0xe9, 0x55, 0xf6, 0xcf, 0x80, 0xf7, 0xb2, 0xdf, 0x26, 0x58, 0x9c, 0x6f, 0xf1, 0xf0, 0x77, 0xd8, 0x2f, 0x2c, 0x8b, 0x6f, 0xb4, 0xf8, 0xed, 0xd5, 0xc9, 0x88, 0xd9, 0xc0, 0x5a, 0x24, 0x49, 0x8e, 0xe8, 0x67, 0xac, 0x92, 0x94, 0xa8, 0x24, 0x19, 0x3d, 0x80, 0x5, 0xc, 0xb5, 0xcc, 0x45, 0x18, 0xc9, 0x6c, 0xb2, 0x42, 0xc7, 0x97, 0x7d, 0x48, 0x97, 0xa5, 0x98, 0xdf, 0x30, 0x82, 0x6d, 0x2e, 0x43, 0x33, 0x1a, 0x51, 0xc9, 0x81, 0x78, 0x1e, 0x69, 0x4f, 0xe4, 0x3, 0xdb, 0xea, 0xaa, 0x5f, 0xe5, 0x6}, + {0x3d, 0x7c, 0x1d, 0x87, 0xb2, 0xd4, 0xd5, 0xa7, 0x7a, 0xcc, 0x87, 0x77, 0xb5, 0x14, 0x80, 0xb0, 0xdd, 0x43, 0x8a, 0x70, 0xda, 0x99, 0xb, 0xe6, 0xd0, 0xda, 0x68, 0xf1, 0xe9, 0x61, 0x54, 0x3b, 0xe0, 0x4a, 0x4f, 0x57, 0x1b, 0xc3, 0xec, 0xfb, 0x52, 0x9e, 0xe1, 0x18, 0x5b, 0xe4, 0x38, 0x9b, 0xcb, 0x81, 0x7d, 0xcd, 0x75, 0x17, 0x5e, 0xde, 0xea, 0x53, 0x76, 0x78, 0xd3, 0x23, 0x69, 0x1f, 0xa7, 0x1b, 0x8c, 0x9a, 0x2f, 0x44, 0x82, 0xf0, 0x89, 0x95, 0xb8, 0xe7, 0xd0, 0xea, 0xdd, 0x7b, 0x79, 0x94, 0x65, 0x16, 0xdc, 0xa1, 0x62, 0x68, 0x8c, 0x64, 0x99, 0x59, 0x9, 0xbb, 0xe7, 0x2a, 0x79, 0xe0, 0x23, 0xc7}, } // Generate keys, fingerprints and messages diff --git a/e2e/auth/encryptDecrypt_test.go b/e2e/auth/encryptDecrypt_test.go index 55ef8bccfb28c25e444229d9480ccd34b92cc676..135331534121d09f3e42e37b79c8033a117a2695 100644 --- a/e2e/auth/encryptDecrypt_test.go +++ b/e2e/auth/encryptDecrypt_test.go @@ -21,18 +21,18 @@ func TestPayloadEncryptDecrypt_Consistency(t *testing.T) { // The expected values for encrypted messages, MACs and fingerprints expectedEncrypted := []string{ - "+3MVB9C4Du0ZhxtWvmNj", - "3Ojy0GrTUMvS6UhLpPPJ", - "Yu28P6zSrS7Oi9N2nBlW", - "ZOhelsMi43Pwy30SYgts", - "urmsCpmQke9zRJ/1t66x", + "99KCYpcHb7O2RsVF/zRz", + "O5eNOVs9BAcEi4leA5P9", + "zXrMJJ1fHxO9i0zKHv9a", + "aRTXHn0au6WM+nypLSrq", + "/q/m4sI3ImXrw6mBGu4C", } expectedMac := []string{ - "MGJP05Y0xZyYtQpyB5uOCNoQh1dJgkxD4HZHCr3kUWE=", - "UKBqjSAP7E8aoG6IV2mI3L8Q2C3o2ES0wgYghwQv0NM=", - "C4PkJU9BdJ/P7ZvCnL2rKk073x1qLRlsZ60qqKSeWiE=", - "V5Nx3tG66jJQPeliY+o2Ahxm1uPZFImKOwazfPJa+QA=", - "CCcno9q+/1hWBLVYrI61zcHVgOqERZ2AzOdFL6q5C7I=", + "SIaOcC2qec+e2ow3Vxw4gFp/MikAhS3otVxj00TCYII=", + "e8UN1yfN4Zs2ws2xFWKnZQ3TQUn0zkwmr7p1Ofa5h/0=", + "B914VCyWYyGGK2yX55BNBRDko468GxN1gqVXVglHIco=", + "Wl99M0Dx/65/lx8yQ9RDLSKPEqq0H37nNmBtewo3zFc=", + "Fb4oIsCZjXHpvxIdzFfo70HsSGR2Pn/ysuA2RLvG3hc=", } expectedFingerprints := []string{ "4juO1SAC6IG67PVQvuf+t1CtLP7r752Ul6hPk0J4jyM=", diff --git a/e2e/auth/mac.go b/e2e/auth/mac.go index a8b532b841d36dab868b6cae4ceadfc3a15f63f8..397b2e57ad1bed9431cd2af7ca8a71369aeb2287 100644 --- a/e2e/auth/mac.go +++ b/e2e/auth/mac.go @@ -13,15 +13,20 @@ package auth import ( "bytes" "gitlab.com/elixxir/crypto/hash" - "crypto/hmac" ) // MakeMac returns the MAC for the given payload. func MakeMac(baseKey, encryptedPayload []byte) []byte { - h := hmac.New(hash.DefaultHash, baseKey) + //suppress because we just panic and a nil hash will panic anyhow + h, _ := hash.NewCMixHash() + // This will panic if we got an error in the line above, but does nothing + // if it worked. + h.Reset() + + h.Write(baseKey) h.Write(encryptedPayload) - sum := h.Sum(nil) + sum := h.Sum(nil) // The first bit must be 0. sum[0] &= 0x7F diff --git a/e2e/auth/mac_test.go b/e2e/auth/mac_test.go index 5247f30baf42540e83ac697d2ff7eac80855f23e..a4c7fadc9eb2dbca46f1fed6aae3862ea948190c 100644 --- a/e2e/auth/mac_test.go +++ b/e2e/auth/mac_test.go @@ -18,11 +18,11 @@ import ( func TestMakeMac_Consistency(t *testing.T) { expected := []string{ - "XNc4xg5johaQAwOAU25kTGPnFJWwdizyp1R8QO0bXos=", - "FOxMuD6rLUL4KZdtq87uTrJk7ul2roTMqAFNvp6F6NY=", - "IaJMMU+N06DHXWdrmjmh09mUwZtJKZgjmh1BG7awX9g=", - "J9Epes8QZ33f2ZXYnhCo74Wisej3MdntuNLeeC8JDSM=", - "dBGm2a7tVKOk0t9c9dnS2cERGi89j0dWXJMDlFmK9hQ=", + "V0/c2vPAzwypqyVmlq5y28InATGkiBbkLbzrUIFHntE=", + "NkZ/F91nRrL5O9kZ3dse74k0hWZ7iFXVW7zyrupaj2U=", + "F8+59YYSpgFwrqjNhxGdUcudYPQiY4VVhEVhcueY09g=", + "fZ4iPmfjFgwfdkOiHFaMTo+bPguKMXsNyD+QJtnKg3M=", + "T+blUgM7MtX+VpUinOeT9txhCRJEfFZDBBhGF1lAuhk=", } grp := getGrp() diff --git a/e2e/encrypt.go b/e2e/encrypt.go index 94998863d16cb349b34bcf6150d682ef2ba2e612..88053a4a2946cb19de823ab633e0c7c5806ff1ac 100644 --- a/e2e/encrypt.go +++ b/e2e/encrypt.go @@ -10,19 +10,16 @@ package e2e import ( "gitlab.com/elixxir/primitives/format" - "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/salsa20" ) -// Crypt uses XChaCha20 to encrypt or decrypt a message with the passed key using the +// CryptUnsafe Salsa20 encrypts or decrypts a message with the passed key using the +// Crypt Salsa20 encrypts or decrypts a message with the passed key using the // fingerprint as a nonce func Crypt(key Key, fingerprint format.Fingerprint, msg []byte) []byte { out := make([]byte, len(msg)) - nonce := fingerprint[:chacha20.NonceSizeX] - cipher, err := chacha20.NewUnauthenticatedCipher(key[:], nonce) - if err != nil { - panic(err) - } - cipher.XORKeyStream(out, msg) + keyArray := [32]byte(key) + salsa20.XORKeyStream(out, msg, fingerprint[:24], &keyArray) // Return the result return out } diff --git a/e2e/encrypt_test.go b/e2e/encrypt_test.go index d47e738aa11081f39c87c63e37fd77d866eee859..3077bf6d3d11919d72d5e276bf8da62215e8eb7a 100644 --- a/e2e/encrypt_test.go +++ b/e2e/encrypt_test.go @@ -40,18 +40,18 @@ func TestEncrypt_Consistency(t *testing.T) { const messageSize = 100 // Set up expected values with base64 encoding expectedMsgs := []string{ - "+gueVocoCTzjwQ4x2kYHR+otKpon0T7NIvUgrC4WTB34sVJv2msD+fsp509zVZxCk9R4" + - "l8HWxSbxQXy7xvzNjp4c1U1G/p0J9xzIVTPxdaYo5NIDS7kd4brTSDFWv3GhmAae" + - "1A==", - "SDy5LnQuKrmnM53BxHFkL+NOvj8bGWm5j2iJVoRoZVkrJqahrjlG4E3zbCiI/uXqqna6" + - "Q1nBZWhv1YmW1Leh3t0lBIfirj/0xJOwm2Bm8Cb3tvMXrZ6+m5b+l7oqrR2hjCyZ" + - "Xg==", - "L7vuk4rtDZYu+YzcCEch62j07LM8cAxN9/Tq9rRuVKhptrxO+97iwcWnqC/kjKciP5hR" + - "kj7IFTo5bUJBi1yGWA5x1mp1TyQuHwcvHUsDEjXppokZrEW1wnsGXx9omIBvqca+" + - "8w==", - "D5WfKGLBkgA8Sg8VWhVUeFm2RjIArxOS5luwcCxkQkTO2ULh/9MqL7MvJ/rEPcryX9vO" + - "NaCgY9wn1V6aYpZkSFzFvIsDKJDnfE/rz6hrDBm6X2x6EmDDb2MCAXYrmvHdQaa/" + - "/A==", + "UGVCeJkjdpZ4iVHs4DaJCZSHMS0bs5fpF9mb8ZBkat+o/mUXe1JCRBbgF0Z6whcy3m3z" + + "eBYp4/Tgdt3hhSssxONndKrel/Xkfi08/lfTZNLqbzDw/42SCss1Sq5S/QT6D3os" + + "iA==", + "aDW1HLOxKC0eFOjFGwj4AGyvnumbrXzA9axxu9sVGzcbvWb7ar04+IHS4IA/K2QXgLW+" + + "RofNVjZHICha4HT3aI3sbY2ZYScsqhdJBUH5ivx/uUlwh7Pt2d6qtPwhyO1ZwFFA" + + "FA==", + "HqKPDP9Hvai61hFc5UKCq84ryjWI4WdMih5WZP+Kj4jbVYuG5ckbEzN75sO6jYOZGIzg" + + "2M3Kjo4lUDIu9QUx7UCbyiLcCiqGK9OuQ89PtxhNR6aCHm374LD78AUtrEkMlcTy" + + "Og==", + "PPYCnDivI7m8xwctIVeslg/KYnbl3BLWiOOpcniiAezg+KDQ7iWARvpk5TFy7PaLIlFn" + + "4fSYK7cb1hZt1KdHKJvXoVICR5a3SbzVQ2RN1XPzbFvlf6A8nvVR2NXrBWBr8a7K" + + "Lg==", } // Generate keys, fingerprints and messages var keys []Key diff --git a/e2e/singleUse/mac.go b/e2e/singleUse/mac.go index 7a3de99fc41c65b7de152b6e61fc30e4883be02a..810076b7daee8ce5c59241a408172cb5d1ace963 100644 --- a/e2e/singleUse/mac.go +++ b/e2e/singleUse/mac.go @@ -9,8 +9,8 @@ package singleUse import ( "bytes" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/crypto/hash" - "crypto/hmac" ) const macSalt = "singleUseMacSalt" @@ -18,9 +18,18 @@ const macSalt = "singleUseMacSalt" // MakeMAC generates the MAC used in both the transmission and response CMIX // messages. func MakeMAC(key []byte, encryptedPayload []byte) []byte { - h := hmac.New(hash.DefaultHash, key) + // Create new hash + h, err := hash.NewCMixHash() + if err != nil { + jww.ERROR.Panicf("Failed to create new hash for single-use MAC: %v", err) + } + + // Hash the key, encrypted payload, and salt + h.Write(key) h.Write(encryptedPayload) h.Write([]byte(macSalt)) + + // Get hash bytes mac := h.Sum(nil) // Set the first bit as zero to ensure everything stays in the group diff --git a/e2e/singleUse/mac_test.go b/e2e/singleUse/mac_test.go index 20979ed45baf4eeb8670f0cf8ee197e687b87972..e1c6a0a006cad59d5d2943fca7bcf20cc59136db 100644 --- a/e2e/singleUse/mac_test.go +++ b/e2e/singleUse/mac_test.go @@ -18,16 +18,16 @@ import ( // Tests that the generated MACs do not change. func TestMAC_Consistency(t *testing.T) { expectedMacs := []string{ - "MS9siixMT9/wskcdoQhmuLXCD7wK3h6yf0cWF3ZodTQ=", - "XLCWSXRdRlDyBZ8Wy0soO0MB0XgOUdhRX9HAd5RDUVk=", - "fM67dZ5G4ce2CF2MneYH29izP4OsKv5k0wQuyjLlLuk=", - "LBK5gesIs8sOUU9slTh8VGOZKKrTHXtXLmmLgKP25J0=", - "G5Nm5GbKiLT0tfJkYWYkgFEY8IxVQHJATj0TfVi9i0k=", - "PPvlpHWQN5Ear436vPcgpbjLNkH9ZK/ZgrW6xwbNbvM=", - "CnlszFIGBZnuHfipIAvQa5aprg2bUD27EkmI2wzJ9G4=", - "XanqEhRX6MMmFNyJA8qGiOzn4pvof72uQE5NoM096OM=", - "XqK6aJspygyh6z4e5wXQo/TkSvBy1rJtMVlv+OAFUm4=", - "TqiTyffLDLclCmRiCH2TeKQk5Lx/Z8SSdAU9s+sHl2g=", + "P5Arek8yIlKVmM4IHJTOycUph0RLeiP0emA0DCx4z90=", + "P9LcMFLn+q8/6SOSb9rrYpLyn3X5MMuephBSOtIF4M0=", + "UOPiUuATfn9C/KjmFZdA4zTfIykMb0HIgELKLbixrtk=", + "UYUHQLjbyDBdZn/MTNQBgrvUQPN0MnVpdYEI0iB/Q68=", + "fArOwzcunIaDYoIgtViaoBOkL2/v95Hm+6KRTEE6F9A=", + "XMhNPEyxy8q0p+bsjGHPQL5vzA+HyqUoooHXrTBEYF4=", + "IDJ4iTo9IcNB/oR5RP45de53SxuWsSSKlYcmGInQtoU=", + "Z4QqQfBp0ezUzAU2MHBUR9K0Bdl9Z3WF5Rcy553fb+8=", + "HthTNmjJ78iCdjMX+zSyhabsiCEE8QmH/AsDFfH8yUA=", + "GnE0KJAwk594cKLt6i2kHAqMJZ8DnXv7XyrByU27F/g=", } prng := rand.New(rand.NewSource(42)) @@ -113,16 +113,16 @@ func TestMAC_Unique(t *testing.T) { // Happy path. func TestVerifyMAC(t *testing.T) { expectedMACs := []string{ - "MS9siixMT9/wskcdoQhmuLXCD7wK3h6yf0cWF3ZodTQ=", - "XLCWSXRdRlDyBZ8Wy0soO0MB0XgOUdhRX9HAd5RDUVk=", - "fM67dZ5G4ce2CF2MneYH29izP4OsKv5k0wQuyjLlLuk=", - "LBK5gesIs8sOUU9slTh8VGOZKKrTHXtXLmmLgKP25J0=", - "G5Nm5GbKiLT0tfJkYWYkgFEY8IxVQHJATj0TfVi9i0k=", - "PPvlpHWQN5Ear436vPcgpbjLNkH9ZK/ZgrW6xwbNbvM=", - "CnlszFIGBZnuHfipIAvQa5aprg2bUD27EkmI2wzJ9G4=", - "XanqEhRX6MMmFNyJA8qGiOzn4pvof72uQE5NoM096OM=", - "XqK6aJspygyh6z4e5wXQo/TkSvBy1rJtMVlv+OAFUm4=", - "TqiTyffLDLclCmRiCH2TeKQk5Lx/Z8SSdAU9s+sHl2g=", + "P5Arek8yIlKVmM4IHJTOycUph0RLeiP0emA0DCx4z90=", + "P9LcMFLn+q8/6SOSb9rrYpLyn3X5MMuephBSOtIF4M0=", + "UOPiUuATfn9C/KjmFZdA4zTfIykMb0HIgELKLbixrtk=", + "UYUHQLjbyDBdZn/MTNQBgrvUQPN0MnVpdYEI0iB/Q68=", + "fArOwzcunIaDYoIgtViaoBOkL2/v95Hm+6KRTEE6F9A=", + "XMhNPEyxy8q0p+bsjGHPQL5vzA+HyqUoooHXrTBEYF4=", + "IDJ4iTo9IcNB/oR5RP45de53SxuWsSSKlYcmGInQtoU=", + "Z4QqQfBp0ezUzAU2MHBUR9K0Bdl9Z3WF5Rcy553fb+8=", + "HthTNmjJ78iCdjMX+zSyhabsiCEE8QmH/AsDFfH8yUA=", + "GnE0KJAwk594cKLt6i2kHAqMJZ8DnXv7XyrByU27F/g=", } prng := rand.New(rand.NewSource(42)) diff --git a/fileTransfer/crypt.go b/fileTransfer/crypt.go index b27f5f740dd2eb7d51f675ed9ac213b5598c49a6..6fcf550249c8a39f16ad4ef669c0a5d19dfb68d4 100644 --- a/fileTransfer/crypt.go +++ b/fileTransfer/crypt.go @@ -16,8 +16,13 @@ package fileTransfer import ( "github.com/pkg/errors" - "gitlab.com/elixxir/primitives/format" - "golang.org/x/crypto/chacha20" + "gitlab.com/xx_network/crypto/csprng" + "golang.org/x/crypto/salsa20" +) + +// NonceSize is the size of the nonce in bytes. +const ( + NonceSize = 8 ) // Error messages @@ -29,49 +34,50 @@ const ( // part key is generated from the transfer key and the fingerprint number. A // random nonce is generated as padding for the ciphertext and used as part of // the encryption. -func EncryptPart(transferKey TransferKey, partBytes []byte, fpNum uint16, fp format.Fingerprint) (ciphertext, mac []byte, err error) { +func EncryptPart(transferKey TransferKey, partBytes []byte, fpNum uint16, + rng csprng.Source) (ciphertext, mac, nonce []byte, + err error) { + + nonce, err = csprng.Generate(NonceSize, rng) + if err != nil { + return nil, nil, nil, err + } // Generate the part key and redefine as array partKey := getPartKey(transferKey, fpNum) + partKeyArray := [32]byte(partKey) // Create byte slice to store encrypted data ciphertextLen := len(partBytes) ciphertext = make([]byte, ciphertextLen) - // ChaCha20 encrypt file part bytes - cipher, err := chacha20.NewUnauthenticatedCipher(partKey[:], fp[:chacha20.NonceSizeX]) - if err != nil { - panic(err) - } - cipher.XORKeyStream(ciphertext, partBytes) + // Salsa20 encrypt file part bytes + salsa20.XORKeyStream(ciphertext, partBytes, nonce, &partKeyArray) // Create file part MAC - mac = createPartMAC(fp[:], partBytes, partKey) + mac = createPartMAC(nonce, partBytes, partKey) // The nonce and ciphertext are returned separately - return ciphertext, mac, nil + return ciphertext, mac, nonce, nil } // DecryptPart decrypts an individual file part. The part key and nonce are used // to decrypt the ciphertext. -func DecryptPart(transferKey TransferKey, ciphertext, mac []byte, - fpNum uint16, fp format.Fingerprint) (filePartBytes []byte, err error) { +func DecryptPart(transferKey TransferKey, ciphertext, nonce, mac []byte, + fpNum uint16) (filePartBytes []byte, err error) { // Generate the part key and redefine as array partKey := getPartKey(transferKey, fpNum) + partKeyArray := [32]byte(partKey) // Create byte slice to store decrypted data filePartBytes = make([]byte, len(ciphertext)) - // ChaCha20 encrypt file part bytes - cipher, err := chacha20.NewUnauthenticatedCipher(partKey[:], fp[:chacha20.NonceSizeX]) - if err != nil { - panic(err) - } - cipher.XORKeyStream(filePartBytes, ciphertext) + // Salsa20 decrypt encrypted file part bytes + salsa20.XORKeyStream(filePartBytes, ciphertext, nonce, &partKeyArray) // Return an error if the MAC cannot be validated - if !verifyPartMAC(fp[:], filePartBytes, mac, partKey) { + if !verifyPartMAC(nonce, filePartBytes, mac, partKey) { return nil, errors.New(macMismatchErr) } diff --git a/fileTransfer/crypt_test.go b/fileTransfer/crypt_test.go index 08dcba05745ff25be5dcf76633ac075d955e18b8..bc719a60ea523906cd7a6b2c4deb2bb2597e6327 100644 --- a/fileTransfer/crypt_test.go +++ b/fileTransfer/crypt_test.go @@ -14,7 +14,6 @@ import ( "math/rand" "strconv" "testing" - "gitlab.com/elixxir/primitives/format" ) // Consistency test for EncryptPart. @@ -22,16 +21,16 @@ func TestEncryptPart_Consistency(t *testing.T) { prng := NewPrng(42) // The expected values for encrypted messages and MACs expectedValues := []struct{ encrPart, mac string }{ - {"P5aImOP0c5OhG2g=", "Z8cPIX3zOOhqRGas2fODIozwxKuX0Gv9NdTmAwDPB9E="}, - {"zBfS1Jh3M+5IJ6s=", "Gu4DYQT7Y2cQ/6xOCgukAPUzL7ezy5ywuw3gbuzpmt0="}, - {"H7WWNFGtYZr/bmo=", "baDwObK6aukr1egK0R8/U3Zicsx5PvHFdCwaC5c19UY="}, - {"MSLjaczLmqrm8AE=", "UiqMNzA8oNowFx/91ne5G8lWs/Pr3Un/sP180W2HP0k="}, - {"moiunm7hg6Wyag4=", "XSpK/MKKTC2kZQXKPiWmthpQOiOcgCdzfjvTO3+NECQ="}, - {"wHmh9im367tJ9yQ=", "MIdJibyECF1veMZmql62xCNQEaKzgcuJtOBjhewExNA="}, - {"lJ1IKBOeo6Q/mrI=", "GK/0dPDvHj7VmWzveLDcsk12Wj4JY+JZkZjyP7GGT/4="}, - {"ylcp4jK3CxeqerQ=", "NB+iYXJVU5uX1BikekC62OtM48QllxyHAscdcEiFbAs="}, - {"k9hB2wqt7P6NrY0=", "KobYc8cu7WHL+uxAenvijFe1fdecCwTx4/OBzTSCvM4="}, - {"fmK35rHs7Nj8wfc=", "SFT2NuDirNGWLiG5K22mF4+7ONcnSb7U4nj2X/OG2MY="}, + {"/pJCVL8FzUpxaWI=", "T02QGQlg36ko8FH26IgxCyKsuLrS7KqkU/3DJlNOfAs="}, + {"AFyk+pU2+maQNkA=", "O3V8fAsI3Tmrau81b3rn7/vUD2HMrWFlCljZNUtokro="}, + {"z9aOLbSwqkn/XDI=", "NijSEkNo/Czzw7zeNR+3lfyBZtOQRBVQcrEIEmjD3ls="}, + {"fY/a+Jc8lzjNioM=", "PzRQ9X5BpvTWvUTNBtiuLqOhB2MjR7Wqh5aU4eGX2bg="}, + {"4sXWEZ5D+AXXZB8=", "KPdq2Hx8dyySNzZ5rhQUEquJjVP2KKF1WaN0orTunD0="}, + {"sHBfFDPrs2Q9CGg=", "ZEPZRdZWyxP0VMHeXA9o/tjd4R2QPEG1j1jA/Uk1DWU="}, + {"NrVAkRa5fwcczXs=", "GlIoH7jZ/pAJ2LfzpWNQKbM9nJaDxouvpWX6CgueSjk="}, + {"ffyeHJpZwYBpsWg=", "B9oDoFSeF1j4Bs414nFUixcfawZ+kTIwFNhXXNT3vMc="}, + {"4WdM4SAE43ybQIU=", "CtRmKeXVfs6jNnDvQOreM9H4G+iCEO/PE7eTATIkhRE="}, + {"fvbi3mt2Ui1POVA=", "RoXczfWjqZpnOGqRdZoZNVL4g/uZcH/HeMvQNIE0Vsk="}, } kwy, err := NewTransferKey(prng) @@ -39,12 +38,11 @@ func TestEncryptPart_Consistency(t *testing.T) { t.Fatalf("Failed to generate transfer key: %+v", err) } + nonceMap := make(map[string]bool, len(expectedValues)) + for i, expected := range expectedValues { payload := []byte("payloadMsg" + strconv.Itoa(i)) - fpBytes := make([]byte, format.KeyFPLen) - prng.Read(fpBytes) - fp := format.NewFingerprint(fpBytes) - ecr, mac, err := EncryptPart(kwy, payload, uint16(i), fp) + ecr, mac, nonce, err := EncryptPart(kwy, payload, uint16(i), prng) if err != nil { t.Errorf("EncryptPart returned an error (%d): %+v", i, err) } @@ -62,6 +60,14 @@ func TestEncryptPart_Consistency(t *testing.T) { t.Errorf("MAC does not match expected (%d)"+ "\nexpected: %s\nreceived: %s", i, expected.mac, mac64) } + + // Verify the nonce is unique + nonce64 := base64.StdEncoding.EncodeToString(nonce) + if nonceMap[nonce64] { + t.Errorf("Padding not unique (%d): %s", i, nonce64) + } else { + nonceMap[nonce64] = true + } } } @@ -77,15 +83,12 @@ func TestEncryptPart_DecryptPart(t *testing.T) { for i := uint16(0); i < 25; i++ { message := make([]byte, 32) _, _ = prng.Read(message) - fpBytes := make([]byte, format.KeyFPLen) - prng.Read(fpBytes) - fp := format.NewFingerprint(fpBytes) - ecr, mac, err := EncryptPart(key, message, uint16(i), fp) + ecr, mac, nonce, err := EncryptPart(key, message, i, prng) if err != nil { t.Errorf("Failed to encrypt part %d: %+v", i, err) } - dec, err := DecryptPart(key, ecr, mac, uint16(i), fp) + dec, err := DecryptPart(key, ecr, nonce, mac, i) if err != nil { t.Errorf("Failed to decrypt part: %+v", err) } @@ -109,10 +112,7 @@ func TestEncryptPart_DecryptPart_InvalidMacError(t *testing.T) { for i := uint16(0); i < 25; i++ { message := make([]byte, 32) _, _ = prng.Read(message) - fpBytes := make([]byte, format.KeyFPLen) - prng.Read(fpBytes) - fp := format.NewFingerprint(fpBytes) - ecr, mac, err := EncryptPart(key, message, i, fp) + ecr, mac, nonce, err := EncryptPart(key, message, i, prng) if err != nil { t.Errorf("Failed to encrypt part %d: %+v", i, err) } @@ -120,7 +120,7 @@ func TestEncryptPart_DecryptPart_InvalidMacError(t *testing.T) { // Generate invalid MAC _, _ = prng.Read(mac) - _, err = DecryptPart(key, ecr, mac, i, fp) + _, err = DecryptPart(key, ecr, nonce, mac, i) if err == nil || err.Error() != macMismatchErr { t.Errorf("DecryptPart did not return the expected error when the "+ "MAC is invalid.\nexpected: %s\nreceived: %+v", diff --git a/fileTransfer/mac.go b/fileTransfer/mac.go index c8657d60dffe040ad9164080d93ec34f4942052b..aa4ac38f4d76f070c3fc17280b6170ebae9ee4a3 100644 --- a/fileTransfer/mac.go +++ b/fileTransfer/mac.go @@ -17,7 +17,6 @@ package fileTransfer import ( "bytes" "gitlab.com/elixxir/crypto/hash" - "crypto/hmac" ) // CreateTransferMAC creates a MAC for the entire file. This is for consistency @@ -36,9 +35,14 @@ func VerifyTransferMAC(fileData []byte, key TransferKey, mac []byte) bool { // createPartMAC creates the MAC for the given file part, its padding, and the // part key. func createPartMAC(nonce, partData []byte, partKey partKey) []byte { - h := hmac.New(hash.DefaultHash, partKey.Bytes()) + h, _ := hash.NewCMixHash() + + h.Reset() + h.Write(nonce) h.Write(partData) + h.Write(partKey.Bytes()) + mac := h.Sum(nil) // Set the first bit to be 0 to comply with the group requirements in the diff --git a/fileTransfer/mac_test.go b/fileTransfer/mac_test.go index 1a05581cea0d90379efcd51c43ed9e0ca5226e5e..da267f07f8f50d6311f49d590f6e12c5143e4fc7 100644 --- a/fileTransfer/mac_test.go +++ b/fileTransfer/mac_test.go @@ -116,10 +116,10 @@ func TestVerifyTransferMAC_BadMacError(t *testing.T) { // a potentially breaking change. func Test_createPartMAC_Consistency(t *testing.T) { expectedMessageMACs := []string{ - "B/2L77dMU5QmoSEyhz9/JIjSezj1bmjb9b6d5iQPt0E=", - "YYrFtOitkyaf1sIYHf5zlBR/kpKS2HPPP6azWdriwgE=", - "IDwozKX8l/eZkkEDHGrWDvlUaVTQaoNFy9f1u7KlYHM=", - "eXlpn2e1By/q/pxWtW5jMJNNvjAQ+gxC2YI38hCvo3g=", + "ISRt4iNQz+F6X4scQO4uW80ZbiWLGTkS43y3r+ZN5/w=", + "DK0IMW8yyeG7SeKNEAPVsEhY5WV4SnAniRlc2s2CVOk=", + "NEUP552b77A2tSSNCE8z1n+RBjM7MgM/GVpzsnGHmY8=", + "PTQS8MpHxl69fwBpZjbikQBGf9I7g/WDQYN0nm3Uejg=", } // Construct a deterministic prng for testing diff --git a/group/crypt.go b/group/crypt.go index 931a9c300235e12bb0de52cd97ba58702e132a45..6b5a8d729a0fb86c3350af7b9e699684dac8fc13 100644 --- a/group/crypt.go +++ b/group/crypt.go @@ -4,7 +4,7 @@ // Use of this source code is governed by a license that can be found in the LICENSE file // //////////////////////////////////////////////////////////////////////////////////////////// -// The internal message format for group messaging is encrypted using XChaCha20 +// The internal message format for group messaging is encrypted using Salsa20 // with the group key and key fingerprint. package group @@ -14,12 +14,12 @@ import ( "gitlab.com/elixxir/primitives/format" ) -// Encrypt encrypts the internal message with XChaCha20. +// Encrypt encrypts the internal message with Salsa20. func Encrypt(key CryptKey, keyFingerprint format.Fingerprint, internalMsg []byte) []byte { return auth.Crypt(key[:], keyFingerprint.Bytes(), internalMsg) } -// Decrypt decrypts the encrypted internal message with XChaCha20. +// Decrypt decrypts the encrypted internal message with Salsa20. func Decrypt(key CryptKey, keyFingerprint format.Fingerprint, encryptedInternalMsg []byte) []byte { return auth.Crypt(key[:], keyFingerprint.Bytes(), encryptedInternalMsg) } diff --git a/group/mac.go b/group/mac.go index c66c671821d437a97d05bdfbf9880c7e20ca6b0b..33fe15c85d77a000cd8e6e3386a4a98fa13e197a 100644 --- a/group/mac.go +++ b/group/mac.go @@ -12,16 +12,18 @@ package group import ( "bytes" "gitlab.com/elixxir/crypto/cyclic" - "crypto/hmac" - "gitlab.com/elixxir/crypto/hash" + "golang.org/x/crypto/blake2b" ) // NewMAC generates a MAC for the encrypted internal message and the recipient's // Diffie–Hellman key. func NewMAC(key CryptKey, encryptedInternalMsg []byte, recipientDhKey *cyclic.Int) []byte { - h := hmac.New(hash.DefaultHash, key[:]) + // Hash the key, the encrypted message, and DH key + h, _ := blake2b.New256(nil) + h.Write(key[:]) h.Write(encryptedInternalMsg) h.Write(recipientDhKey.Bytes()) + mac := h.Sum(nil) // Set the first bit to be 0 to comply with the group requirements in the diff --git a/group/mac_test.go b/group/mac_test.go index 00b5274411469387ff66b0ef2f2a1cfdfbd82834..7fa06270b0f960a8a99483b8fcf9053d76513384 100644 --- a/group/mac_test.go +++ b/group/mac_test.go @@ -16,16 +16,16 @@ import ( func TestNewMAC_Consistency(t *testing.T) { prng := rand.New(rand.NewSource(42)) expectedMACs := []string{ - "ZhmxYgs565joaUDPAqTwaoGxT4sVrdbla8rGvfdbmlo=", - "cz5qdjK4AnaVkxXTHNurMDBwEan0ngNnFNYIeDwaN74=", - "SK141v83ahxHoGdLbSoEfLR81k3grUsc5HCWbebdF/0=", - "csIMTmjxuunP9dm3YbG4+l0KsVfoIa0k5hjZKzEHNd0=", - "VFyFNBHhGD8unpYwIXb00k6jsVnfhJY2oq+659n1jhw=", - "TFXdUjisQ2SMmANoM/nx8ZXzjgee3G5UYpa8KJ72++s=", - "W8edrqCRGcnVgVVzPguE4zWarJ7UMqofcwNsvah8mD0=", - "NkcOGXJ95HOkq5okfgQ4h5VY4eCcDl2FPdFSPzhpLdw=", - "WkFMHOaZ+kDTIBF3DKpjzXSgcNqMLxXHsnhMcKafqT4=", - "aHmhf4l6IIntsbZW0fp2dq6nq2MWWjisBktHSMkhyRA=", + "VoY325mBeeAUPNI3XSEVB6wHSsoLvOaXSW8rXIzQBDY=", + "W1enM94zLJ3naWmHCWyLcSO38kGmvWmlefG0aII7FZM=", + "OtvHUpfQd6Vi5Kyqs5n1jPKOqXJ3zn0MUMP97QT8em0=", + "KhCFLBeGlleZKL+UbW3+rV7m7LwGZuZonLX0R2ENWfE=", + "e5835g9L19Un9wYG82g8xnIc1bFgIwaETgyOTrAl17I=", + "K4H7lpOmW22BuiqRudCO52Ex2ZL42XH313lZgPX2Vio=", + "KK6bwNzGbRD33GvSwozRDKojTj1L41vWSEbbY9UebxA=", + "VpmSedjVhSGQGBgcazCicITYyRj6n9B0qPGAQh23c+Q=", + "Twt2/HrO0fWxW8bmSTGOlT4NCbNmQQSauyOA1iqN4SQ=", + "ZlNetJzIkiQpUEpFOMGYthhcmXbkMFuYDrXJPUpB0fs=", } for i, expected := range expectedMACs { diff --git a/hash/hash.go b/hash/hash.go index 3dd89ae20ceed47d5d63cf1bdc8119f089858610..50773375ba199fb008cc14c290b0c601a06bbc95 100644 --- a/hash/hash.go +++ b/hash/hash.go @@ -15,7 +15,6 @@ import ( "crypto/sha256" "golang.org/x/crypto/blake2b" "hash" - "fmt" ) // NewCMixHash returns the current cMix hash implementation @@ -25,15 +24,6 @@ func NewCMixHash() (hash.Hash, error) { return blake2b.New256(nil) } -// DefaultHash returns a CMIX hash or panics -func DefaultHash() hash.Hash { - h, err := blake2b.New256(nil) - if err != nil { - panic(fmt.Sprintf("Could not initialize blake2b: %+v", err)) - } - return h -} - // CMixHash type is currently BLAKE2b_256 var CMixHash = crypto.BLAKE2b_256