further optimizations

This commit is contained in:
Johannes Loher 2016-07-05 20:34:52 +02:00
parent 20dc2ff534
commit e51b852a39
2 changed files with 55 additions and 96 deletions

View file

@ -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)

14
source/utility.d Normal file
View file

@ -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;
}