diff --git a/source/salsa20.d b/source/salsa20.d index f45f64f..cc8426a 100644 --- a/source/salsa20.d +++ b/source/salsa20.d @@ -12,6 +12,8 @@ import utility; public: +// TODO: Implement random access + auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) if (isInputRange!R && is(ElementType!R : ubyte)) { @@ -20,26 +22,28 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) private: ulong count; R range; - ubyte[] salsaSection; + ubyte[64] salsaSection; + uint salsaCounter; public: bool empty() @property { - return range.empty || (count == ulong.max && salsaSection.empty); + return range.empty || (count == ulong.max && salsaCounter == 64); } ubyte front() @property { assert(!empty); - return range.front ^ salsaSection.front; + return range.front ^ salsaSection[salsaCounter]; } void popFront() { assert(!empty); - salsaSection.popFront(); - if (salsaSection.empty) + if (++salsaCounter == 64) { + import std.stdio; salsaSection = salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(++count))); + salsaCounter = 0; } range.popFront(); } @@ -47,11 +51,25 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) { auto save() @property { - return rangeResult(count, range.save, salsaSection.dup); + return rangeResult(count, range.save, salsaSection); } } } - return rangeResult(0UL, range, salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(0UL))).dup); + return rangeResult(0UL, range, salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(0UL)))); +} + +// TODO: Create more unittest!!! + +@safe unittest +{ + ubyte[] test = new ubyte[64]; + ubyte[32] key; + ubyte[8] nonce; + test = test.salsa20Cipher(key, nonce).array; + assert(test == [154,151,246, 91,155, 76,114, 27,150, 10,103, 33, 69,252,168,212, + 227, 46,103,249, 17, 30,169,121,206,156, 72, 38,128,106,238,230, + 61,233,192,218, 43,215,249, 30,188,178, 99,155,249,137,198, 37, + 27, 41,191, 56,211,154,155,220,231,197, 95, 75, 42,193, 42, 57]); } private: @@ -242,27 +260,27 @@ ubyte[64] salsa20(in ubyte[64] input) pure nothrow @safe @nogc @safe unittest { ubyte[64] test0 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; test0 = salsa20(test0); ubyte[64] test1 = [211,159, 13,115, 76, 55, 82,183, 3,117,222, 37,191,187,234,136, - 49,237,179, 48, 1,106,178,219,175,199,166, 48, 86, 16,179,207, - 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113,238, 55,204, 36, - 79,201,235, 79, 3, 81,156, 47,203, 26,244,243, 88,118,104, 54]; + 49,237,179, 48, 1,106,178,219,175,199,166, 48, 86, 16,179,207, + 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113,238, 55,204, 36, + 79,201,235, 79, 3, 81,156, 47,203, 26,244,243, 88,118,104, 54]; test1 = salsa20(test1); ubyte[64] test2 = [ 88,118,104, 54, 79,201,235, 79, 3, 81,156, 47,203, 26,244,243, - 191,187,234,136,211,159, 13,115, 76, 55, 82,183, 3,117,222, 37, - 86, 16,179,207, 49,237,179, 48, 1,106,178,219,175,199,166, 48, - 238, 55,204, 36, 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113]; + 191,187,234,136,211,159, 13,115, 76, 55, 82,183, 3,117,222, 37, + 86, 16,179,207, 49,237,179, 48, 1,106,178,219,175,199,166, 48, + 238, 55,204, 36, 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113]; test2 = salsa20(test2); ubyte[64] test3 = [ 6,124, 83,146, 38,191, 9, 50, 4,161, 47,222,122,182,223,185, - 75, 27, 0,216, 16,122, 7, 89,162,104,101,147,213, 21, 54, 95, - 225,253,139,176,105,132, 23,116, 76, 41,176,207,221, 34,157,108, - 94, 94, 99, 52, 90,117, 91,220,146,190,239,143,196,176,130,186]; + 75, 27, 0,216, 16,122, 7, 89,162,104,101,147,213, 21, 54, 95, + 225,253,139,176,105,132, 23,116, 76, 41,176,207,221, 34,157,108, + 94, 94, 99, 52, 90,117, 91,220,146,190,239,143,196,176,130,186]; foreach (i; 0..1000000) test3 = salsa20(test3);