Skip to content
Snippets Groups Projects
Commit d6713e35 authored by Richard T. Carback III's avatar Richard T. Carback III
Browse files

Revert "Merge branch 'dev' into 'release'"

This reverts merge request !23
parent 0657d748
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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
......
......@@ -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=",
......
......@@ -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
......
......@@ -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()
......
......@@ -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
}
......@@ -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
......
......@@ -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
......
......@@ -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))
......
......@@ -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)
}
......
......@@ -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",
......
......@@ -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
......
......@@ -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
......
......@@ -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)
}
......@@ -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
......
......@@ -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 {
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment