diff --git a/e2e/auth/crypt.go b/e2e/auth/crypt.go index 7d391256ce52f37ae536b8de74d6f07c6c809efe..c2d8c8f6cc2ada5ff2698420326466952de0b0ff 100644 --- a/e2e/auth/crypt.go +++ b/e2e/auth/crypt.go @@ -8,23 +8,27 @@ package auth import ( jww "github.com/spf13/jwalterweatherman" - "golang.org/x/crypto/salsa20" + "golang.org/x/crypto/chacha20" ) -// Required length of the nonce within Salsa20 -const NonceLength = 24 +// Required length of the nonce within XChaCha20 +const NonceLength = chacha20.NonceSizeX -// Crypt Salsa20 encrypts or decrypts a message with the passed key and vector +// Crypt XChaCha20 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 Salsa20 encryption/decryption + // Bound check that the vector is long enough for XChaCha20 encryption/decryption if len(vector) < NonceLength { jww.ERROR.Panicf("Vector is not of sufficient length for encryption/decryption") } out := make([]byte, len(msg)) - var keyArray [32]byte - copy(keyArray[:], key) - salsa20.XORKeyStream(out, msg, vector[:NonceLength], &keyArray) + nonce := vector[:NonceLength] + + cipher, err := chacha20.NewUnauthenticatedCipher(key[:], nonce) + if err != nil { + panic(err) + } + cipher.XORKeyStream(out, msg) // Return the result return out diff --git a/e2e/auth/crypt_test.go b/e2e/auth/crypt_test.go index 94f7b979902155bbf9965b3450500892674d818b..eb886169c72138dd0984752eee12998c1cc22a87 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{ - {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}, + {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}, } // Generate keys, fingerprints and messages diff --git a/e2e/auth/encryptDecrypt_test.go b/e2e/auth/encryptDecrypt_test.go index 135331534121d09f3e42e37b79c8033a117a2695..55ef8bccfb28c25e444229d9480ccd34b92cc676 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{ - "99KCYpcHb7O2RsVF/zRz", - "O5eNOVs9BAcEi4leA5P9", - "zXrMJJ1fHxO9i0zKHv9a", - "aRTXHn0au6WM+nypLSrq", - "/q/m4sI3ImXrw6mBGu4C", + "+3MVB9C4Du0ZhxtWvmNj", + "3Ojy0GrTUMvS6UhLpPPJ", + "Yu28P6zSrS7Oi9N2nBlW", + "ZOhelsMi43Pwy30SYgts", + "urmsCpmQke9zRJ/1t66x", } expectedMac := []string{ - "SIaOcC2qec+e2ow3Vxw4gFp/MikAhS3otVxj00TCYII=", - "e8UN1yfN4Zs2ws2xFWKnZQ3TQUn0zkwmr7p1Ofa5h/0=", - "B914VCyWYyGGK2yX55BNBRDko468GxN1gqVXVglHIco=", - "Wl99M0Dx/65/lx8yQ9RDLSKPEqq0H37nNmBtewo3zFc=", - "Fb4oIsCZjXHpvxIdzFfo70HsSGR2Pn/ysuA2RLvG3hc=", + "MGJP05Y0xZyYtQpyB5uOCNoQh1dJgkxD4HZHCr3kUWE=", + "UKBqjSAP7E8aoG6IV2mI3L8Q2C3o2ES0wgYghwQv0NM=", + "C4PkJU9BdJ/P7ZvCnL2rKk073x1qLRlsZ60qqKSeWiE=", + "V5Nx3tG66jJQPeliY+o2Ahxm1uPZFImKOwazfPJa+QA=", + "CCcno9q+/1hWBLVYrI61zcHVgOqERZ2AzOdFL6q5C7I=", } expectedFingerprints := []string{ "4juO1SAC6IG67PVQvuf+t1CtLP7r752Ul6hPk0J4jyM=", diff --git a/e2e/auth/mac.go b/e2e/auth/mac.go index 397b2e57ad1bed9431cd2af7ca8a71369aeb2287..a8b532b841d36dab868b6cae4ceadfc3a15f63f8 100644 --- a/e2e/auth/mac.go +++ b/e2e/auth/mac.go @@ -13,20 +13,15 @@ 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 { - //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 := hmac.New(hash.DefaultHash, baseKey) h.Write(encryptedPayload) - 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 a4c7fadc9eb2dbca46f1fed6aae3862ea948190c..5247f30baf42540e83ac697d2ff7eac80855f23e 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{ - "V0/c2vPAzwypqyVmlq5y28InATGkiBbkLbzrUIFHntE=", - "NkZ/F91nRrL5O9kZ3dse74k0hWZ7iFXVW7zyrupaj2U=", - "F8+59YYSpgFwrqjNhxGdUcudYPQiY4VVhEVhcueY09g=", - "fZ4iPmfjFgwfdkOiHFaMTo+bPguKMXsNyD+QJtnKg3M=", - "T+blUgM7MtX+VpUinOeT9txhCRJEfFZDBBhGF1lAuhk=", + "XNc4xg5johaQAwOAU25kTGPnFJWwdizyp1R8QO0bXos=", + "FOxMuD6rLUL4KZdtq87uTrJk7ul2roTMqAFNvp6F6NY=", + "IaJMMU+N06DHXWdrmjmh09mUwZtJKZgjmh1BG7awX9g=", + "J9Epes8QZ33f2ZXYnhCo74Wisej3MdntuNLeeC8JDSM=", + "dBGm2a7tVKOk0t9c9dnS2cERGi89j0dWXJMDlFmK9hQ=", } grp := getGrp() diff --git a/e2e/encrypt.go b/e2e/encrypt.go index 88053a4a2946cb19de823ab633e0c7c5806ff1ac..94998863d16cb349b34bcf6150d682ef2ba2e612 100644 --- a/e2e/encrypt.go +++ b/e2e/encrypt.go @@ -10,16 +10,19 @@ package e2e import ( "gitlab.com/elixxir/primitives/format" - "golang.org/x/crypto/salsa20" + "golang.org/x/crypto/chacha20" ) -// 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 +// Crypt uses XChaCha20 to encrypt or decrypt 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)) - keyArray := [32]byte(key) - salsa20.XORKeyStream(out, msg, fingerprint[:24], &keyArray) + nonce := fingerprint[:chacha20.NonceSizeX] + cipher, err := chacha20.NewUnauthenticatedCipher(key[:], nonce) + if err != nil { + panic(err) + } + cipher.XORKeyStream(out, msg) // Return the result return out } diff --git a/e2e/encrypt_test.go b/e2e/encrypt_test.go index 3077bf6d3d11919d72d5e276bf8da62215e8eb7a..d47e738aa11081f39c87c63e37fd77d866eee859 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{ - "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==", + "+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==", } // Generate keys, fingerprints and messages var keys []Key diff --git a/e2e/singleUse/mac.go b/e2e/singleUse/mac.go index 810076b7daee8ce5c59241a408172cb5d1ace963..7a3de99fc41c65b7de152b6e61fc30e4883be02a 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,18 +18,9 @@ const macSalt = "singleUseMacSalt" // MakeMAC generates the MAC used in both the transmission and response CMIX // messages. func MakeMAC(key []byte, encryptedPayload []byte) []byte { - // 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 := hmac.New(hash.DefaultHash, 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 e1c6a0a006cad59d5d2943fca7bcf20cc59136db..20979ed45baf4eeb8670f0cf8ee197e687b87972 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{ - "P5Arek8yIlKVmM4IHJTOycUph0RLeiP0emA0DCx4z90=", - "P9LcMFLn+q8/6SOSb9rrYpLyn3X5MMuephBSOtIF4M0=", - "UOPiUuATfn9C/KjmFZdA4zTfIykMb0HIgELKLbixrtk=", - "UYUHQLjbyDBdZn/MTNQBgrvUQPN0MnVpdYEI0iB/Q68=", - "fArOwzcunIaDYoIgtViaoBOkL2/v95Hm+6KRTEE6F9A=", - "XMhNPEyxy8q0p+bsjGHPQL5vzA+HyqUoooHXrTBEYF4=", - "IDJ4iTo9IcNB/oR5RP45de53SxuWsSSKlYcmGInQtoU=", - "Z4QqQfBp0ezUzAU2MHBUR9K0Bdl9Z3WF5Rcy553fb+8=", - "HthTNmjJ78iCdjMX+zSyhabsiCEE8QmH/AsDFfH8yUA=", - "GnE0KJAwk594cKLt6i2kHAqMJZ8DnXv7XyrByU27F/g=", + "MS9siixMT9/wskcdoQhmuLXCD7wK3h6yf0cWF3ZodTQ=", + "XLCWSXRdRlDyBZ8Wy0soO0MB0XgOUdhRX9HAd5RDUVk=", + "fM67dZ5G4ce2CF2MneYH29izP4OsKv5k0wQuyjLlLuk=", + "LBK5gesIs8sOUU9slTh8VGOZKKrTHXtXLmmLgKP25J0=", + "G5Nm5GbKiLT0tfJkYWYkgFEY8IxVQHJATj0TfVi9i0k=", + "PPvlpHWQN5Ear436vPcgpbjLNkH9ZK/ZgrW6xwbNbvM=", + "CnlszFIGBZnuHfipIAvQa5aprg2bUD27EkmI2wzJ9G4=", + "XanqEhRX6MMmFNyJA8qGiOzn4pvof72uQE5NoM096OM=", + "XqK6aJspygyh6z4e5wXQo/TkSvBy1rJtMVlv+OAFUm4=", + "TqiTyffLDLclCmRiCH2TeKQk5Lx/Z8SSdAU9s+sHl2g=", } 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{ - "P5Arek8yIlKVmM4IHJTOycUph0RLeiP0emA0DCx4z90=", - "P9LcMFLn+q8/6SOSb9rrYpLyn3X5MMuephBSOtIF4M0=", - "UOPiUuATfn9C/KjmFZdA4zTfIykMb0HIgELKLbixrtk=", - "UYUHQLjbyDBdZn/MTNQBgrvUQPN0MnVpdYEI0iB/Q68=", - "fArOwzcunIaDYoIgtViaoBOkL2/v95Hm+6KRTEE6F9A=", - "XMhNPEyxy8q0p+bsjGHPQL5vzA+HyqUoooHXrTBEYF4=", - "IDJ4iTo9IcNB/oR5RP45de53SxuWsSSKlYcmGInQtoU=", - "Z4QqQfBp0ezUzAU2MHBUR9K0Bdl9Z3WF5Rcy553fb+8=", - "HthTNmjJ78iCdjMX+zSyhabsiCEE8QmH/AsDFfH8yUA=", - "GnE0KJAwk594cKLt6i2kHAqMJZ8DnXv7XyrByU27F/g=", + "MS9siixMT9/wskcdoQhmuLXCD7wK3h6yf0cWF3ZodTQ=", + "XLCWSXRdRlDyBZ8Wy0soO0MB0XgOUdhRX9HAd5RDUVk=", + "fM67dZ5G4ce2CF2MneYH29izP4OsKv5k0wQuyjLlLuk=", + "LBK5gesIs8sOUU9slTh8VGOZKKrTHXtXLmmLgKP25J0=", + "G5Nm5GbKiLT0tfJkYWYkgFEY8IxVQHJATj0TfVi9i0k=", + "PPvlpHWQN5Ear436vPcgpbjLNkH9ZK/ZgrW6xwbNbvM=", + "CnlszFIGBZnuHfipIAvQa5aprg2bUD27EkmI2wzJ9G4=", + "XanqEhRX6MMmFNyJA8qGiOzn4pvof72uQE5NoM096OM=", + "XqK6aJspygyh6z4e5wXQo/TkSvBy1rJtMVlv+OAFUm4=", + "TqiTyffLDLclCmRiCH2TeKQk5Lx/Z8SSdAU9s+sHl2g=", } prng := rand.New(rand.NewSource(42)) diff --git a/fileTransfer/crypt.go b/fileTransfer/crypt.go index 6fcf550249c8a39f16ad4ef669c0a5d19dfb68d4..b27f5f740dd2eb7d51f675ed9ac213b5598c49a6 100644 --- a/fileTransfer/crypt.go +++ b/fileTransfer/crypt.go @@ -16,13 +16,8 @@ package fileTransfer import ( "github.com/pkg/errors" - "gitlab.com/xx_network/crypto/csprng" - "golang.org/x/crypto/salsa20" -) - -// NonceSize is the size of the nonce in bytes. -const ( - NonceSize = 8 + "gitlab.com/elixxir/primitives/format" + "golang.org/x/crypto/chacha20" ) // Error messages @@ -34,50 +29,49 @@ 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, - rng csprng.Source) (ciphertext, mac, nonce []byte, - err error) { - - nonce, err = csprng.Generate(NonceSize, rng) - if err != nil { - return nil, nil, nil, err - } +func EncryptPart(transferKey TransferKey, partBytes []byte, fpNum uint16, fp format.Fingerprint) (ciphertext, mac []byte, err error) { // 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) - // Salsa20 encrypt file part bytes - salsa20.XORKeyStream(ciphertext, partBytes, nonce, &partKeyArray) + // ChaCha20 encrypt file part bytes + cipher, err := chacha20.NewUnauthenticatedCipher(partKey[:], fp[:chacha20.NonceSizeX]) + if err != nil { + panic(err) + } + cipher.XORKeyStream(ciphertext, partBytes) // Create file part MAC - mac = createPartMAC(nonce, partBytes, partKey) + mac = createPartMAC(fp[:], partBytes, partKey) // The nonce and ciphertext are returned separately - return ciphertext, mac, nonce, nil + return ciphertext, mac, nil } // DecryptPart decrypts an individual file part. The part key and nonce are used // to decrypt the ciphertext. -func DecryptPart(transferKey TransferKey, ciphertext, nonce, mac []byte, - fpNum uint16) (filePartBytes []byte, err error) { +func DecryptPart(transferKey TransferKey, ciphertext, mac []byte, + fpNum uint16, fp format.Fingerprint) (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)) - // Salsa20 decrypt encrypted file part bytes - salsa20.XORKeyStream(filePartBytes, ciphertext, nonce, &partKeyArray) + // ChaCha20 encrypt file part bytes + cipher, err := chacha20.NewUnauthenticatedCipher(partKey[:], fp[:chacha20.NonceSizeX]) + if err != nil { + panic(err) + } + cipher.XORKeyStream(filePartBytes, ciphertext) // Return an error if the MAC cannot be validated - if !verifyPartMAC(nonce, filePartBytes, mac, partKey) { + if !verifyPartMAC(fp[:], filePartBytes, mac, partKey) { return nil, errors.New(macMismatchErr) } diff --git a/fileTransfer/crypt_test.go b/fileTransfer/crypt_test.go index bc719a60ea523906cd7a6b2c4deb2bb2597e6327..08dcba05745ff25be5dcf76633ac075d955e18b8 100644 --- a/fileTransfer/crypt_test.go +++ b/fileTransfer/crypt_test.go @@ -14,6 +14,7 @@ import ( "math/rand" "strconv" "testing" + "gitlab.com/elixxir/primitives/format" ) // Consistency test for EncryptPart. @@ -21,16 +22,16 @@ func TestEncryptPart_Consistency(t *testing.T) { prng := NewPrng(42) // The expected values for encrypted messages and MACs expectedValues := []struct{ encrPart, mac string }{ - {"/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="}, + {"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="}, } kwy, err := NewTransferKey(prng) @@ -38,11 +39,12 @@ 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)) - ecr, mac, nonce, err := EncryptPart(kwy, payload, uint16(i), prng) + fpBytes := make([]byte, format.KeyFPLen) + prng.Read(fpBytes) + fp := format.NewFingerprint(fpBytes) + ecr, mac, err := EncryptPart(kwy, payload, uint16(i), fp) if err != nil { t.Errorf("EncryptPart returned an error (%d): %+v", i, err) } @@ -60,14 +62,6 @@ 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 - } } } @@ -83,12 +77,15 @@ func TestEncryptPart_DecryptPart(t *testing.T) { for i := uint16(0); i < 25; i++ { message := make([]byte, 32) _, _ = prng.Read(message) - ecr, mac, nonce, err := EncryptPart(key, message, i, prng) + fpBytes := make([]byte, format.KeyFPLen) + prng.Read(fpBytes) + fp := format.NewFingerprint(fpBytes) + ecr, mac, err := EncryptPart(key, message, uint16(i), fp) if err != nil { t.Errorf("Failed to encrypt part %d: %+v", i, err) } - dec, err := DecryptPart(key, ecr, nonce, mac, i) + dec, err := DecryptPart(key, ecr, mac, uint16(i), fp) if err != nil { t.Errorf("Failed to decrypt part: %+v", err) } @@ -112,7 +109,10 @@ func TestEncryptPart_DecryptPart_InvalidMacError(t *testing.T) { for i := uint16(0); i < 25; i++ { message := make([]byte, 32) _, _ = prng.Read(message) - ecr, mac, nonce, err := EncryptPart(key, message, i, prng) + fpBytes := make([]byte, format.KeyFPLen) + prng.Read(fpBytes) + fp := format.NewFingerprint(fpBytes) + ecr, mac, err := EncryptPart(key, message, i, fp) 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, nonce, mac, i) + _, err = DecryptPart(key, ecr, mac, i, fp) 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 aa4ac38f4d76f070c3fc17280b6170ebae9ee4a3..c8657d60dffe040ad9164080d93ec34f4942052b 100644 --- a/fileTransfer/mac.go +++ b/fileTransfer/mac.go @@ -17,6 +17,7 @@ package fileTransfer import ( "bytes" "gitlab.com/elixxir/crypto/hash" + "crypto/hmac" ) // CreateTransferMAC creates a MAC for the entire file. This is for consistency @@ -35,14 +36,9 @@ 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, _ := hash.NewCMixHash() - - h.Reset() - + h := hmac.New(hash.DefaultHash, partKey.Bytes()) 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 da267f07f8f50d6311f49d590f6e12c5143e4fc7..1a05581cea0d90379efcd51c43ed9e0ca5226e5e 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{ - "ISRt4iNQz+F6X4scQO4uW80ZbiWLGTkS43y3r+ZN5/w=", - "DK0IMW8yyeG7SeKNEAPVsEhY5WV4SnAniRlc2s2CVOk=", - "NEUP552b77A2tSSNCE8z1n+RBjM7MgM/GVpzsnGHmY8=", - "PTQS8MpHxl69fwBpZjbikQBGf9I7g/WDQYN0nm3Uejg=", + "B/2L77dMU5QmoSEyhz9/JIjSezj1bmjb9b6d5iQPt0E=", + "YYrFtOitkyaf1sIYHf5zlBR/kpKS2HPPP6azWdriwgE=", + "IDwozKX8l/eZkkEDHGrWDvlUaVTQaoNFy9f1u7KlYHM=", + "eXlpn2e1By/q/pxWtW5jMJNNvjAQ+gxC2YI38hCvo3g=", } // Construct a deterministic prng for testing diff --git a/group/crypt.go b/group/crypt.go index 6b5a8d729a0fb86c3350af7b9e699684dac8fc13..931a9c300235e12bb0de52cd97ba58702e132a45 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 Salsa20 +// The internal message format for group messaging is encrypted using XChaCha20 // 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 Salsa20. +// Encrypt encrypts the internal message with XChaCha20. func Encrypt(key CryptKey, keyFingerprint format.Fingerprint, internalMsg []byte) []byte { return auth.Crypt(key[:], keyFingerprint.Bytes(), internalMsg) } -// Decrypt decrypts the encrypted internal message with Salsa20. +// Decrypt decrypts the encrypted internal message with XChaCha20. 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 33fe15c85d77a000cd8e6e3386a4a98fa13e197a..c66c671821d437a97d05bdfbf9880c7e20ca6b0b 100644 --- a/group/mac.go +++ b/group/mac.go @@ -12,18 +12,16 @@ package group import ( "bytes" "gitlab.com/elixxir/crypto/cyclic" - "golang.org/x/crypto/blake2b" + "crypto/hmac" + "gitlab.com/elixxir/crypto/hash" ) // 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 { - // Hash the key, the encrypted message, and DH key - h, _ := blake2b.New256(nil) - h.Write(key[:]) + h := hmac.New(hash.DefaultHash, 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 7fa06270b0f960a8a99483b8fcf9053d76513384..00b5274411469387ff66b0ef2f2a1cfdfbd82834 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{ - "VoY325mBeeAUPNI3XSEVB6wHSsoLvOaXSW8rXIzQBDY=", - "W1enM94zLJ3naWmHCWyLcSO38kGmvWmlefG0aII7FZM=", - "OtvHUpfQd6Vi5Kyqs5n1jPKOqXJ3zn0MUMP97QT8em0=", - "KhCFLBeGlleZKL+UbW3+rV7m7LwGZuZonLX0R2ENWfE=", - "e5835g9L19Un9wYG82g8xnIc1bFgIwaETgyOTrAl17I=", - "K4H7lpOmW22BuiqRudCO52Ex2ZL42XH313lZgPX2Vio=", - "KK6bwNzGbRD33GvSwozRDKojTj1L41vWSEbbY9UebxA=", - "VpmSedjVhSGQGBgcazCicITYyRj6n9B0qPGAQh23c+Q=", - "Twt2/HrO0fWxW8bmSTGOlT4NCbNmQQSauyOA1iqN4SQ=", - "ZlNetJzIkiQpUEpFOMGYthhcmXbkMFuYDrXJPUpB0fs=", + "ZhmxYgs565joaUDPAqTwaoGxT4sVrdbla8rGvfdbmlo=", + "cz5qdjK4AnaVkxXTHNurMDBwEan0ngNnFNYIeDwaN74=", + "SK141v83ahxHoGdLbSoEfLR81k3grUsc5HCWbebdF/0=", + "csIMTmjxuunP9dm3YbG4+l0KsVfoIa0k5hjZKzEHNd0=", + "VFyFNBHhGD8unpYwIXb00k6jsVnfhJY2oq+659n1jhw=", + "TFXdUjisQ2SMmANoM/nx8ZXzjgee3G5UYpa8KJ72++s=", + "W8edrqCRGcnVgVVzPguE4zWarJ7UMqofcwNsvah8mD0=", + "NkcOGXJ95HOkq5okfgQ4h5VY4eCcDl2FPdFSPzhpLdw=", + "WkFMHOaZ+kDTIBF3DKpjzXSgcNqMLxXHsnhMcKafqT4=", + "aHmhf4l6IIntsbZW0fp2dq6nq2MWWjisBktHSMkhyRA=", } for i, expected := range expectedMACs { diff --git a/hash/hash.go b/hash/hash.go index 50773375ba199fb008cc14c290b0c601a06bbc95..3dd89ae20ceed47d5d63cf1bdc8119f089858610 100644 --- a/hash/hash.go +++ b/hash/hash.go @@ -15,6 +15,7 @@ import ( "crypto/sha256" "golang.org/x/crypto/blake2b" "hash" + "fmt" ) // NewCMixHash returns the current cMix hash implementation @@ -24,6 +25,15 @@ 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