diff --git a/source/salsa20.d b/source/salsa20.d index fad16c5..f45f64f 100644 --- a/source/salsa20.d +++ b/source/salsa20.d @@ -1,10 +1,14 @@ module salsa20; -private import std.string : format; -private import std.range : isInputRange, isForwardRange, ElementType; -private import std.array; +private: + +import std.string : format; +import std.range : isInputRange, isForwardRange, ElementType; +import std.array; + +import bitmanip; +import utility; -private import bitmanip; public: @@ -35,10 +39,7 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) salsaSection.popFront(); if (salsaSection.empty) { - ubyte[16] n; - n[0..8] = nonce; - n[8..16] = littleEndianInv(0UL); - salsaSection = salsa20Exp(key, n).dup; + salsaSection = salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(++count))); } range.popFront(); } @@ -50,10 +51,7 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) } } } - ubyte[16] n; - n[0..8] = nonce; - n[8..16] = littleEndianInv(0UL); - return rangeResult(0UL, range, salsa20Exp(key, n).dup); + return rangeResult(0UL, range, salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(0UL))).dup); } private: @@ -66,7 +64,7 @@ enum string quarterRound(alias _x0, alias _x1, alias _x2, alias _x3) = q{ }.format(__traits(identifier, _x0), __traits(identifier, _x1), __traits(identifier, _x2), __traits(identifier, _x3)); -unittest +@safe unittest { uint a1 = 0x00000000, a2 = 0x00000000, a3 = 0x00000000, a4 = 0x00000000, b1 = 0x00000001, b2 = 0x00000000, b3 = 0x00000000, b4 = 0x00000000, @@ -110,7 +108,7 @@ enum string rowRound(alias _x00, alias _x01, alias _x02, alias _x03, __traits(identifier, _x12), __traits(identifier, _x13), __traits(identifier, _x14), __traits(identifier, _x15)); -unittest +@safe unittest { uint y00 = 0x00000001, y01 = 0x00000000, y02 = 0x00000000, y03 = 0x00000000, y04 = 0x00000001, y05 = 0x00000000, y06 = 0x00000000, y07 = 0x00000000, @@ -162,7 +160,7 @@ enum string colRound(alias _x00, alias _x01, alias _x02, alias _x03, __traits(identifier, _x12), __traits(identifier, _x13), __traits(identifier, _x14), __traits(identifier, _x15)); -unittest +@safe unittest { uint y00 = 0x00000001, y01 = 0x00000000, y02 = 0x00000000, y03 = 0x00000000, y04 = 0x00000001, y05 = 0x00000000, y06 = 0x00000000, y07 = 0x00000000, @@ -198,16 +196,7 @@ unittest 0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8]); } -ubyte[64] salsa20(in ubyte[64] input) pure nothrow @safe -/*in -{ - assert(input.length == 64); -} -out(result) -{ - assert(result.length == 64); -} -body*/ +ubyte[64] salsa20(in ubyte[64] input) pure nothrow @safe @nogc { auto x00 = littleEndian(input[00..04]), x01 = littleEndian(input[04..08]), x02 = littleEndian(input[08..12]), x03 = littleEndian(input[12..16]), @@ -232,35 +221,25 @@ body*/ x08, x09, x10, x11, x12, x13, x14, x15)); } - ubyte[64] buf; - buf[00..04] = littleEndianInv(x00 + y00); - buf[04..08] = littleEndianInv(x01 + y01); - buf[08..12] = littleEndianInv(x02 + y02); - buf[12..16] = littleEndianInv(x03 + y03); - buf[16..20] = littleEndianInv(x04 + y04); - buf[20..24] = littleEndianInv(x05 + y05); - buf[24..28] = littleEndianInv(x06 + y06); - buf[28..32] = littleEndianInv(x07 + y07); - buf[32..36] = littleEndianInv(x08 + y08); - buf[36..40] = littleEndianInv(x09 + y09); - buf[40..44] = littleEndianInv(x10 + y10); - buf[44..48] = littleEndianInv(x11 + y11); - buf[48..52] = littleEndianInv(x12 + y12); - buf[52..56] = littleEndianInv(x13 + y13); - buf[56..60] = littleEndianInv(x14 + y14); - buf[60..64] = littleEndianInv(x15 + y15); - return buf; -/* return littleEndianInv(x00 + y00) ~ littleEndianInv(x01 + y01) ~ - littleEndianInv(x02 + y02) ~ littleEndianInv(x03 + y03) ~ - littleEndianInv(x04 + y04) ~ littleEndianInv(x05 + y05) ~ - littleEndianInv(x06 + y06) ~ littleEndianInv(x07 + y07) ~ - littleEndianInv(x08 + y08) ~ littleEndianInv(x09 + y09) ~ - littleEndianInv(x10 + y10) ~ littleEndianInv(x11 + y11) ~ - littleEndianInv(x12 + y12) ~ littleEndianInv(x13 + y13) ~ - littleEndianInv(x14 + y14) ~ littleEndianInv(x15 + y15);*/ + return concat!(ubyte[64])(littleEndianInv(x00 + y00), + littleEndianInv(x01 + y01), + littleEndianInv(x02 + y02), + littleEndianInv(x03 + y03), + littleEndianInv(x04 + y04), + littleEndianInv(x05 + y05), + littleEndianInv(x06 + y06), + littleEndianInv(x07 + y07), + littleEndianInv(x08 + y08), + littleEndianInv(x09 + y09), + littleEndianInv(x10 + y10), + littleEndianInv(x11 + y11), + littleEndianInv(x12 + y12), + littleEndianInv(x13 + y13), + littleEndianInv(x14 + y14), + littleEndianInv(x15 + y15)); } -unittest +@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, @@ -313,55 +292,21 @@ static immutable ubyte[4] sigma1 = [110, 100, 32, 51]; static immutable ubyte[4] sigma2 = [ 50, 45, 98, 121]; static immutable ubyte[4] sigma3 = [116, 101, 32, 107]; -import std.range; -import std.algorithm; -import std.typetuple; - -template expand(alias A, alias C="A[I]") { - auto ref M(alias I)() @property { return mixin(C); } - mixin(q{alias expand = TypeTuple!(} - ~ iota(A.length).map!q{"M!"~text(a)}().join(",") - ~ q{);}); +ubyte[64] salsa20Exp(in ubyte[32] key, in ubyte[16] n) @safe pure nothrow @nogc +{ + return salsa20(concat!(ubyte[64])(sigma0, + key[0..16], + sigma1, + n, + sigma2, + key[16..$], + sigma3)); } -ubyte[64] salsa20Exp(in ubyte[32] key, in ubyte[16] n) @safe pure nothrow -/*in -{ - assert(key.length == 32); - assert(n.length == 16); -} -out(result) -{ - assert(result.length == 64); -} -body*/ -{ - ubyte[64] buf = [ - expand!sigma0, - expand!key[0..16], - expand!sigma1, - expand!n, - expand!sigma2, - expand!key[16..$], - expand!sigma3 - ]; -/* buf[0..4] = sigma0; - buf[4..20] = key[0..16]; - buf[20..24] = sigma1; - buf[24..40] = n; - buf[40..44] = sigma2; - buf[44..60] = key[16..$]; - buf[60..64] = sigma3;*/ - return salsa20(buf); - //return salsa20(σ0 ~ key[0..16] ~ σ1 ~ n ~ σ2 ~ key[16..$] ~ σ3); -} - -unittest +@safe unittest { ubyte[32] key; ubyte[16] n; -/* key.length = 32; - n.length = 16;*/ foreach (i; 0..16) key[i] = cast(ubyte)(i + 1); foreach (i; 16..32) diff --git a/source/utility.d b/source/utility.d new file mode 100644 index 0000000..207c937 --- /dev/null +++ b/source/utility.d @@ -0,0 +1,14 @@ +module utility; + +auto concat(T : E[n], E, size_t n)(in E[][] args...) @nogc +{ + size_t offset = 0; + T result = void; + foreach(arr; args) { + result[offset .. offset+arr.length] = arr; + offset += arr.length; + } + assert(offset == result.length); + return result; +} +