From 98b228d77e0311025e76dd34168f81a5a8fb15aa Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 14 Oct 2015 23:43:07 -0700 Subject: [PATCH] finish lioness implementation, add basic test --- lionness.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ lionness_test.go | 23 ++++++++++++++ sphinx.go | 46 ---------------------------- 3 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 lionness.go create mode 100644 lionness_test.go diff --git a/lionness.go b/lionness.go new file mode 100644 index 000000000..da86e9bb1 --- /dev/null +++ b/lionness.go @@ -0,0 +1,78 @@ +package main + +import ( + "crypto/hmac" + "crypto/sha256" +) + +// lionEncode... +// block cipher with a block size equivalent to our message size +// http://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf (section 6) +func lionessEncode(key [securityParameter]byte, message [messageSize]byte) [messageSize]byte { + var cipherText [messageSize]byte + copy(cipherText[:], message[:]) + + L := cipherText[:securityParameter] + R := cipherText[securityParameter:] + + // Round 1. + // L = L XOR H_k1(R) + h := hmac.New(sha256.New, append(key[:], 0x01)) + h.Write(R) + xor(L[:], h.Sum(nil)[:securityParameter], L[:]) + + // Round 2. + // R = R XOR S(L XOR K_2) + var k2 [securityParameter]byte + xor(k2[:], L[:], key[:]) + xor(R[:], R[:], generateCipherStream(k2, uint(len(R)))) + + // Round 3. + // L = L XOR H_k3(R) + h = hmac.New(sha256.New, append(key[:], 0x03)) + h.Write(R) + xor(L[:], h.Sum(nil)[:securityParameter], L[:]) + + // Round 4. + // R = R XOR S(L XOR K_4) + var k4 [securityParameter]byte + xor(k4[:], L[:], key[:]) + xor(R[:], R[:], generateCipherStream(k4, uint(len(R)))) + + return cipherText +} + +// lionDecode... +func lionessDecode(key [securityParameter]byte, cipherText [messageSize]byte) [messageSize]byte { + var message [messageSize]byte + copy(message[:], cipherText[:]) + + L := message[:securityParameter] + R := message[securityParameter:] + + // Round 4. + // R = R XOR S(L XOR K_4) + var k4 [securityParameter]byte + xor(k4[:], L[:], key[:]) + xor(R[:], R[:], generateCipherStream(k4, uint(len(R)))) + + // Round 3. + // L = L XOR H_k3(R) + h := hmac.New(sha256.New, append(key[:], 0x03)) + h.Write(R) + xor(L[:], h.Sum(nil)[:securityParameter], L[:]) + + // Round 2. + // R = R XOR S(L XOR K_2) + var k2 [securityParameter]byte + xor(k2[:], L[:], key[:]) + xor(R[:], R[:], generateCipherStream(k2, uint(len(R)))) + + // Round 1. + // L = L XOR H_k1(R) + h = hmac.New(sha256.New, append(key[:], 0x01)) + h.Write(R) + xor(L[:], h.Sum(nil)[:securityParameter], L[:]) + + return message +} diff --git a/lionness_test.go b/lionness_test.go new file mode 100644 index 000000000..31af98379 --- /dev/null +++ b/lionness_test.go @@ -0,0 +1,23 @@ +package main + +import ( + "bytes" + "crypto/rand" + "testing" +) + +func TestLionnessCorrectness(t *testing.T) { + var m [messageSize]byte + msg := []byte("hello") + copy(m[:], msg) + + var key [securityParameter]byte + rand.Read(key[:]) + + cipherText := lionessEncode(key, m) + plainText := lionessDecode(key, cipherText) + + if !bytes.Equal(m[:], plainText[:]) { + t.Fatalf("texts not equal") + } +} diff --git a/sphinx.go b/sphinx.go index 018f73a4c..86f061827 100644 --- a/sphinx.go +++ b/sphinx.go @@ -238,52 +238,6 @@ func CreateForwardingMessage(route []*btcec.PublicKey, dest LnAddr, return mixHeader, &onion, nil } -// lionEncode... -// block cipher with a block size equivalent to our message size -// http://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf (section 6) -func lionessEncode(key [securityParameter]byte, message [messageSize]byte) [messageSize]byte { - //var l [securityParameter]byte - //var r [messageSize + securityParameter]byte - - sha := sha256.New() - var cipherText [messageSize]byte - - // Round 1. - sha.Write(message[securityParameter:]) - sha.Write(key[:]) - sha.Write([]byte{1}) - xor(cipherText[:], sha.Sum(nil)[:securityParameter], message[:securityParameter]) - copy(cipherText[securityParameter:], message[securityParameter:]) - - // Round 2. - var k2 [securityParameter]byte - xor(k2[:], cipherText[:securityParameter], key[:]) - block, _ := aes.NewCipher(k2[:]) - stream := cipher.NewCTR(block, bytes.Repeat([]byte{0}, aes.BlockSize)) - stream.XORKeyStream(cipherText[securityParameter:], cipherText[securityParameter:]) - - sha.Reset() - - // Round 3. - sha.Write(cipherText[securityParameter:]) - sha.Write(key[:]) - sha.Write([]byte{3}) - xor(cipherText[:], sha.Sum(nil)[:securityParameter], cipherText[:securityParameter]) - - // Round 4. - var k4 [securityParameter]byte - xor(k4[:], cipherText[:securityParameter], key[:]) - block, _ = aes.NewCipher(k4[:]) - stream = cipher.NewCTR(block, bytes.Repeat([]byte{0}, aes.BlockSize)) - stream.XORKeyStream(cipherText[securityParameter:], cipherText[securityParameter:]) - - return cipherText -} - -// lionDecode... -func lionessDecode() { -} - // calcMac.... func calcMac(key [securityParameter]byte, msg []byte) [securityParameter]byte { hmac := hmac.New(sha256.New, key[:])