223 lines
6.0 KiB
Go
223 lines
6.0 KiB
Go
package doubleratchet
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDhPair(t *testing.T) {
|
|
// Arrange.
|
|
p := dhPair{
|
|
privateKey: []byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
|
|
publicKey: []byte{6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6},
|
|
}
|
|
|
|
// Act.
|
|
var (
|
|
privKey = p.PrivateKey()
|
|
pubKey = p.PublicKey()
|
|
)
|
|
|
|
// Assert.
|
|
require.Equal(t, p.privateKey, privKey)
|
|
require.Equal(t, p.publicKey, pubKey)
|
|
require.Equal(t, fmt.Sprintf(`{privateKey: %s publicKey: %s}`, p.PrivateKey(), p.PublicKey()), p.String())
|
|
}
|
|
|
|
func TestDefaultCrypto_GenerateDH_Basic(t *testing.T) {
|
|
// Arrange.
|
|
c := DefaultCrypto{}
|
|
|
|
// Act.
|
|
pair, err := c.GenerateDH()
|
|
|
|
// Assert.
|
|
require.Nil(t, err)
|
|
|
|
require.EqualValues(t, 0, pair.PrivateKey()[0]&7)
|
|
require.EqualValues(t, 0, pair.PrivateKey()[31]&128)
|
|
require.EqualValues(t, 64, pair.PrivateKey()[31]&64)
|
|
|
|
require.NotEqual(t, nil, pair.PrivateKey())
|
|
require.NotEqual(t, nil, pair.PublicKey())
|
|
require.Len(t, pair.PrivateKey(), 32)
|
|
require.Len(t, pair.PublicKey(), 32)
|
|
require.NotEqual(t, pair.PublicKey(), pair.PrivateKey())
|
|
}
|
|
|
|
func TestDefaultCrypto_GenerateDH_DifferentKeysEveryTime(t *testing.T) {
|
|
// Arrange.
|
|
var (
|
|
c = DefaultCrypto{}
|
|
keys = make(map[string]bool)
|
|
)
|
|
|
|
for i := 0; i < 10; i++ {
|
|
t.Run("", func(t *testing.T) {
|
|
// Act.
|
|
pair, err := c.GenerateDH()
|
|
|
|
// Assert.
|
|
require.Nil(t, err)
|
|
privateKeyString := fmt.Sprintf("%x", pair.PrivateKey())
|
|
publicKeyString := fmt.Sprintf("%x", pair.PublicKey())
|
|
require.False(t, keys[privateKeyString])
|
|
require.False(t, keys[publicKeyString])
|
|
|
|
// Preserve.
|
|
keys[privateKeyString] = true
|
|
keys[publicKeyString] = true
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDefaultCrypto_DH(t *testing.T) {
|
|
// Arrange.
|
|
c := DefaultCrypto{}
|
|
|
|
// Act.
|
|
var (
|
|
alicePair, err1 = c.GenerateDH()
|
|
bobPair, err2 = c.GenerateDH()
|
|
aliceSK, err3 = c.DH(alicePair, bobPair.PublicKey())
|
|
bobSK, err4 = c.DH(bobPair, alicePair.PublicKey())
|
|
)
|
|
|
|
// Assert.
|
|
require.Nil(t, err1)
|
|
require.Nil(t, err2)
|
|
require.Nil(t, err3)
|
|
require.Nil(t, err4)
|
|
require.NotEqual(t, nil, aliceSK)
|
|
require.Equal(t, aliceSK, bobSK)
|
|
}
|
|
|
|
func TestDefaultCrypto_KdfRK(t *testing.T) {
|
|
// Arrange.
|
|
c := DefaultCrypto{}
|
|
|
|
// Act.
|
|
// TODO: Test hk.
|
|
newRK, newCK, _ := c.KdfRK(
|
|
[]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
|
|
[]byte{0x9c, 0x1e, 0x68, 0xab, 0x9d, 0x45, 0xf5, 0x82, 0x35, 0xc4, 0x2, 0xa8, 0x82, 0xa1, 0x46, 0x55, 0x35, 0x41, 0xf1, 0x9d, 0x87, 0x2b, 0x59, 0x24, 0x39, 0x3b, 0x91, 0xf7, 0xda, 0x46, 0x56, 0xf},
|
|
)
|
|
|
|
// Assert.
|
|
require.NotEqual(t, nil, newRK)
|
|
require.NotEqual(t, nil, newCK)
|
|
require.Len(t, newRK, 32)
|
|
require.Len(t, newCK, 32)
|
|
require.NotEqual(t, newRK, newCK)
|
|
}
|
|
|
|
func TestDefaultCrypto_KdfCK(t *testing.T) {
|
|
// Arrange.
|
|
c := DefaultCrypto{}
|
|
|
|
// Act.
|
|
newCK, mk := c.KdfCK([]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})
|
|
|
|
// Assert.
|
|
require.NotEqual(t, nil, newCK)
|
|
require.NotEqual(t, nil, mk)
|
|
require.Len(t, newCK, 32)
|
|
require.Len(t, mk, 32)
|
|
require.NotEqual(t, mk, newCK)
|
|
}
|
|
|
|
func TestDefaultCrypto_deriveEncKeys(t *testing.T) {
|
|
// Arrange.
|
|
c := DefaultCrypto{}
|
|
|
|
// Act.
|
|
encKey, authKey, iv := c.deriveEncKeys([]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})
|
|
|
|
// Assert.
|
|
require.Len(t, encKey, 32)
|
|
require.Len(t, authKey, 32)
|
|
require.Len(t, iv, 16)
|
|
require.NotEqual(t, nil, encKey)
|
|
require.NotEqual(t, nil, authKey)
|
|
require.NotContains(t, encKey, iv)
|
|
require.NotContains(t, authKey, iv)
|
|
require.NotEqual(t, encKey, authKey)
|
|
}
|
|
|
|
func TestDefaultCrypto_computeSignature(t *testing.T) {
|
|
// Arrange.
|
|
var (
|
|
c = DefaultCrypto{}
|
|
ciphertext = []byte{13, 250, 114, 78}
|
|
)
|
|
|
|
// Act.
|
|
signature := c.computeSignature(
|
|
[]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
|
|
ciphertext,
|
|
nil,
|
|
)
|
|
|
|
// Assert.
|
|
require.Len(t, signature, 32)
|
|
require.NotEqual(t, nil, signature)
|
|
}
|
|
|
|
func TestDefaultCrypto_EncryptDecrypt(t *testing.T) {
|
|
// Arrange.
|
|
var (
|
|
c = DefaultCrypto{}
|
|
msg = []byte("1337")
|
|
mk = []byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40}
|
|
)
|
|
|
|
t.Run("no associated data", func(t *testing.T) {
|
|
// Act.
|
|
ciphertext, err := c.Encrypt(mk, msg, nil)
|
|
require.Nil(t, err)
|
|
|
|
plaintext, err := c.Decrypt(mk, ciphertext, nil)
|
|
require.Nil(t, err)
|
|
|
|
// Assert.
|
|
require.Len(t, ciphertext, 16+len(msg)+32) // iv + plaintext length + signature
|
|
require.Equal(t, msg, plaintext)
|
|
})
|
|
|
|
t.Run("same associated data", func(t *testing.T) {
|
|
// Act.
|
|
ciphertext, err := c.Encrypt(mk, msg, []byte("any secret"))
|
|
require.Nil(t, err)
|
|
|
|
plaintext, err := c.Decrypt(mk, ciphertext, []byte("any secret"))
|
|
require.Nil(t, err)
|
|
|
|
// Assert.
|
|
require.Len(t, ciphertext, 32+16+len(msg)) // signature + iv + plaintext length
|
|
require.Equal(t, msg, plaintext)
|
|
})
|
|
|
|
t.Run("different associated data", func(t *testing.T) {
|
|
// Act.
|
|
ciphertext, err := c.Encrypt(mk, msg, []byte("not secret at all"))
|
|
require.Nil(t, err)
|
|
|
|
_, err = c.Decrypt(mk, ciphertext, []byte("any secret"))
|
|
require.EqualError(t, err, "invalid signature")
|
|
})
|
|
|
|
t.Run("malformed signature", func(t *testing.T) {
|
|
// Act.
|
|
ciphertext, err := c.Encrypt(mk, msg, nil)
|
|
require.Nil(t, err)
|
|
|
|
ciphertext[len(ciphertext)-1] ^= 57 // Inverse the last byte in the signature.
|
|
_, err = c.Decrypt(mk, ciphertext, nil)
|
|
|
|
// Assert.
|
|
require.EqualError(t, err, "invalid signature")
|
|
})
|
|
}
|