optimized chacha20, added benchmark functionality, added some 'immutables'
This commit is contained in:
parent
0a9fef2cae
commit
f6a718e331
6 changed files with 152 additions and 121 deletions
|
@ -16,8 +16,8 @@ enum string randomDeviceName = "/dev/random";
|
||||||
|
|
||||||
void encrypt(string keyFileName, Cipher cipher, bool armor)
|
void encrypt(string keyFileName, Cipher cipher, bool armor)
|
||||||
{
|
{
|
||||||
auto key = loadKey(keyFileName, armor);
|
immutable key = loadKey(keyFileName, armor);
|
||||||
ubyte[8] nonce;
|
immutable ubyte[8] nonce;
|
||||||
if (armor)
|
if (armor)
|
||||||
{
|
{
|
||||||
ubyte[base64ChunkSize] buf;
|
ubyte[base64ChunkSize] buf;
|
||||||
|
@ -61,9 +61,9 @@ void encrypt(string keyFileName, Cipher cipher, bool armor)
|
||||||
|
|
||||||
void decrypt(string keyFileName, Cipher cipher, bool armor)
|
void decrypt(string keyFileName, Cipher cipher, bool armor)
|
||||||
{
|
{
|
||||||
import std.range;
|
import std.range : inputRangeObject, InputRange;
|
||||||
auto key = loadKey(keyFileName, armor);
|
immutable key = loadKey(keyFileName, armor);
|
||||||
ubyte[8] nonce;
|
immutable ubyte[8] nonce;
|
||||||
ubyte[chunkSize] buf;
|
ubyte[chunkSize] buf;
|
||||||
int counter;
|
int counter;
|
||||||
InputRange!ubyte r;
|
InputRange!ubyte r;
|
||||||
|
@ -110,6 +110,11 @@ void generateKey(bool armor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bench()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ubyte[32] loadKey(string filename, bool armor)
|
ubyte[32] loadKey(string filename, bool armor)
|
||||||
|
|
11
source/app.d
11
source/app.d
|
@ -7,7 +7,7 @@ import actions;
|
||||||
|
|
||||||
int main(string[] args)
|
int main(string[] args)
|
||||||
{
|
{
|
||||||
bool[string] actions = ["genKey" : false, "encrypt" : false, "decrypt" : false];
|
bool[string] actions = ["genKey" : false, "encrypt" : false, "decrypt" : false, "benchmark" : false];
|
||||||
|
|
||||||
Cipher cipher = Cipher.chacha20;
|
Cipher cipher = Cipher.chacha20;
|
||||||
string keyFileName = "symkey.asc";
|
string keyFileName = "symkey.asc";
|
||||||
|
@ -20,6 +20,7 @@ int main(string[] args)
|
||||||
"Generate a new 256 bit key.", &actions["genKey"],
|
"Generate a new 256 bit key.", &actions["genKey"],
|
||||||
"encrypt|e", "Encrypt a message.", &actions["encrypt"],
|
"encrypt|e", "Encrypt a message.", &actions["encrypt"],
|
||||||
"decrypt|d", "Decrypt a message.", &actions["decrypt"],
|
"decrypt|d", "Decrypt a message.", &actions["decrypt"],
|
||||||
|
"benchmark|b", "Perform some benchmarks.", &actions["benchmark"],
|
||||||
"cipher|c", "The cipher to use (default: %s).".format(cipher), &cipher, "key|k",
|
"cipher|c", "The cipher to use (default: %s).".format(cipher), &cipher, "key|k",
|
||||||
"The file which contains the key (default: %s).".format(keyFileName),
|
"The file which contains the key (default: %s).".format(keyFileName),
|
||||||
&keyFileName, "armor|a", "use ascii-armored I/O.", &armor);
|
&keyFileName, "armor|a", "use ascii-armored I/O.", &armor);
|
||||||
|
@ -50,6 +51,10 @@ int main(string[] args)
|
||||||
{
|
{
|
||||||
decrypt(keyFileName, cipher, armor);
|
decrypt(keyFileName, cipher, armor);
|
||||||
}
|
}
|
||||||
|
else if (actions["benchmark"])
|
||||||
|
{
|
||||||
|
bench();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +77,6 @@ void printHelp(Option[] options)
|
||||||
{
|
{
|
||||||
defaultGetoptPrinter("Usage: ./learncrypt [options]\n\nCommon options:", options[$ - 1 .. $]);
|
defaultGetoptPrinter("Usage: ./learncrypt [options]\n\nCommon options:", options[$ - 1 .. $]);
|
||||||
defaultGetoptPrinter("\nGlobal options:", options[$ - 2 .. $ - 1]);
|
defaultGetoptPrinter("\nGlobal options:", options[$ - 2 .. $ - 1]);
|
||||||
defaultGetoptPrinter("\nActions:", options[0 .. 3]);
|
defaultGetoptPrinter("\nActions:", options[0 .. 4]);
|
||||||
defaultGetoptPrinter("\nAction options:", options[3 .. 5]);
|
defaultGetoptPrinter("\nAction options:", options[4 .. 5]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
module chacha20;
|
module chacha20;
|
||||||
|
|
||||||
private import std.string : format;
|
private:
|
||||||
private import std.range : isInputRange, isForwardRange, ElementType;
|
|
||||||
private import std.array;
|
import std.string : format;
|
||||||
|
import std.range : isInputRange, isForwardRange, ElementType;
|
||||||
|
import std.array;
|
||||||
|
|
||||||
|
import bitmanip;
|
||||||
|
import utility;
|
||||||
|
|
||||||
private import bitmanip;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// TODO: Check unittests (Use reliable software to check if the results are correct)
|
// TODO: Check unittests (Use reliable software to check if the results are correct)
|
||||||
|
|
||||||
|
// TODO: Implement random access
|
||||||
|
|
||||||
auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
|
auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
|
||||||
if (isInputRange!R && is(ElementType!R : ubyte))
|
if (isInputRange!R && is(ElementType!R : ubyte))
|
||||||
{
|
{
|
||||||
|
@ -18,27 +24,26 @@ auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
|
||||||
private:
|
private:
|
||||||
ulong count;
|
ulong count;
|
||||||
R range;
|
R range;
|
||||||
ubyte[] chachaSection;
|
ubyte[64] chachaSection;
|
||||||
|
uint chachaCounter;
|
||||||
public:
|
public:
|
||||||
bool empty() @property
|
bool empty() @property
|
||||||
{
|
{
|
||||||
return range.empty || (count == ulong.max && chachaSection.empty);
|
return range.empty || (count == ulong.max && chachaCounter == 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
ubyte front() @property
|
ubyte front() @property
|
||||||
{
|
{
|
||||||
assert(!empty);
|
assert(!empty);
|
||||||
return range.front ^ chachaSection.front;
|
return range.front ^ chachaSection[chachaCounter];
|
||||||
}
|
}
|
||||||
|
|
||||||
void popFront()
|
void popFront()
|
||||||
{
|
{
|
||||||
assert(!empty);
|
assert(!empty);
|
||||||
chachaSection.popFront();
|
if (++chachaCounter == 64)
|
||||||
if (chachaSection.empty)
|
|
||||||
{
|
{
|
||||||
++count;
|
chachaSection = chacha20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(++count)));
|
||||||
chachaSection = chacha20Exp(key, nonce ~ littleEndianInv(count));
|
|
||||||
}
|
}
|
||||||
range.popFront();
|
range.popFront();
|
||||||
}
|
}
|
||||||
|
@ -46,11 +51,25 @@ auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
|
||||||
{
|
{
|
||||||
auto save() @property
|
auto save() @property
|
||||||
{
|
{
|
||||||
return rangeResult(count, range.save, chachaSection.dup);
|
return rangeResult(count, range.save, chachaSection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rangeResult(0UL, range, chacha20Exp(key, nonce ~ littleEndianInv(0UL)));
|
return rangeResult(0UL, range, chacha20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(0UL))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Create more unittests!!!
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
ubyte[] test = new ubyte[64];
|
||||||
|
ubyte[32] key;
|
||||||
|
ubyte[8] nonce;
|
||||||
|
test = test.chacha20Cipher(key, nonce).array;
|
||||||
|
assert(test == [140,111, 5,175,106, 91,125,127, 60,125, 18, 49, 73, 47,186, 94,
|
||||||
|
234,193,178,253,211,130, 18, 77,243,176, 91,203,126, 83, 82,194,
|
||||||
|
77,251,230, 8,208,202, 74,201,254, 13,148,163, 20, 1,151,129,
|
||||||
|
168,147,213,247, 92, 23,242, 73,135, 68,217,123, 87,123,234,199]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -63,7 +82,7 @@ enum string quarterRound(alias _x0, alias _x1, alias _x2, alias _x3) = q{
|
||||||
}.format(__traits(identifier, _x0), __traits(identifier, _x1),
|
}.format(__traits(identifier, _x0), __traits(identifier, _x1),
|
||||||
__traits(identifier, _x2), __traits(identifier, _x3));
|
__traits(identifier, _x2), __traits(identifier, _x3));
|
||||||
|
|
||||||
unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
uint a1 = 0x00000000, a2 = 0x00000000, a3 = 0x00000000, a4 = 0x00000000,
|
uint a1 = 0x00000000, a2 = 0x00000000, a3 = 0x00000000, a4 = 0x00000000,
|
||||||
b1 = 0x00000001, b2 = 0x00000000, b3 = 0x00000000, b4 = 0x00000000,
|
b1 = 0x00000001, b2 = 0x00000000, b3 = 0x00000000, b4 = 0x00000000,
|
||||||
|
@ -107,7 +126,7 @@ enum string rowRound(alias _x00, alias _x01, alias _x02, alias _x03,
|
||||||
__traits(identifier, _x12), __traits(identifier, _x13),
|
__traits(identifier, _x12), __traits(identifier, _x13),
|
||||||
__traits(identifier, _x14), __traits(identifier, _x15));
|
__traits(identifier, _x14), __traits(identifier, _x15));
|
||||||
|
|
||||||
unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
uint y00 = 0x00000001, y01 = 0x00000000, y02 = 0x00000000, y03 = 0x00000000,
|
uint y00 = 0x00000001, y01 = 0x00000000, y02 = 0x00000000, y03 = 0x00000000,
|
||||||
y04 = 0x00000001, y05 = 0x00000000, y06 = 0x00000000, y07 = 0x00000000,
|
y04 = 0x00000001, y05 = 0x00000000, y06 = 0x00000000, y07 = 0x00000000,
|
||||||
|
@ -125,11 +144,11 @@ unittest
|
||||||
mixin(rowRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
mixin(rowRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15));
|
x08, x09, x10, x11, x12, x13, x14, x15));
|
||||||
|
|
||||||
uint[] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
immutable uint[16] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
||||||
y08, y09, y10, y11, y12, y13, y14, y15];
|
y08, y09, y10, y11, y12, y13, y14, y15];
|
||||||
|
|
||||||
uint[] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
immutable uint[16] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15];
|
x08, x09, x10, x11, x12, x13, x14, x15];
|
||||||
|
|
||||||
assert(test0 == [0x10000001, 0x10000000, 0x00001000, 0x10001001,
|
assert(test0 == [0x10000001, 0x10000000, 0x00001000, 0x10001001,
|
||||||
0x88888808, 0x80808808, 0x80800808, 0x08080080,
|
0x88888808, 0x80808808, 0x80800808, 0x08080080,
|
||||||
|
@ -159,7 +178,7 @@ enum string colRound(alias _x00, alias _x01, alias _x02, alias _x03,
|
||||||
__traits(identifier, _x12), __traits(identifier, _x13),
|
__traits(identifier, _x12), __traits(identifier, _x13),
|
||||||
__traits(identifier, _x14), __traits(identifier, _x15));
|
__traits(identifier, _x14), __traits(identifier, _x15));
|
||||||
|
|
||||||
unittest{
|
@safe unittest{
|
||||||
uint y00 = 0x00000001, y01 = 0x00000000, y02 = 0x00000000, y03 = 0x00000000,
|
uint y00 = 0x00000001, y01 = 0x00000000, y02 = 0x00000000, y03 = 0x00000000,
|
||||||
y04 = 0x00000001, y05 = 0x00000000, y06 = 0x00000000, y07 = 0x00000000,
|
y04 = 0x00000001, y05 = 0x00000000, y06 = 0x00000000, y07 = 0x00000000,
|
||||||
y08 = 0x00000001, y09 = 0x00000000, y10 = 0x00000000, y11 = 0x00000000,
|
y08 = 0x00000001, y09 = 0x00000000, y10 = 0x00000000, y11 = 0x00000000,
|
||||||
|
@ -177,11 +196,11 @@ unittest{
|
||||||
mixin(colRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
mixin(colRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15));
|
x08, x09, x10, x11, x12, x13, x14, x15));
|
||||||
|
|
||||||
uint[] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
immutable uint[16] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
||||||
y08, y09, y10, y11, y12, y13, y14, y15];
|
y08, y09, y10, y11, y12, y13, y14, y15];
|
||||||
|
|
||||||
uint[] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
immutable uint[16] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15];
|
x08, x09, x10, x11, x12, x13, x14, x15];
|
||||||
|
|
||||||
assert(test0 == [0x30000002, 0x00000000, 0x00000000, 0x00000000,
|
assert(test0 == [0x30000002, 0x00000000, 0x00000000, 0x00000000,
|
||||||
0x81811899, 0x00000000, 0x00000000, 0x00000000,
|
0x81811899, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
@ -194,16 +213,7 @@ unittest{
|
||||||
0xf5529d13, 0xfbee0de7, 0x7c5c8c13, 0x9c847b82]);
|
0xf5529d13, 0xfbee0de7, 0x7c5c8c13, 0x9c847b82]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ubyte[] chacha20(in ubyte[] input) @safe nothrow pure
|
ubyte[64] chacha20(in ubyte[64] input) @safe nothrow pure @nogc
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(input.length == 64);
|
|
||||||
}
|
|
||||||
out(result)
|
|
||||||
{
|
|
||||||
assert(result.length == 64);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
{
|
||||||
auto x00 = littleEndian(input[00..04]), x01 = littleEndian(input[04..08]),
|
auto x00 = littleEndian(input[00..04]), x01 = littleEndian(input[04..08]),
|
||||||
x02 = littleEndian(input[08..12]), x03 = littleEndian(input[12..16]),
|
x02 = littleEndian(input[08..12]), x03 = littleEndian(input[12..16]),
|
||||||
|
@ -228,41 +238,49 @@ body
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15));
|
x08, x09, x10, x11, x12, x13, x14, x15));
|
||||||
}
|
}
|
||||||
|
|
||||||
return littleEndianInv(x00 + y00) ~ littleEndianInv(x01 + y01) ~
|
return concat!(ubyte[64])(littleEndianInv(x00 + y00),
|
||||||
littleEndianInv(x02 + y02) ~ littleEndianInv(x03 + y03) ~
|
littleEndianInv(x01 + y01),
|
||||||
littleEndianInv(x04 + y04) ~ littleEndianInv(x05 + y05) ~
|
littleEndianInv(x02 + y02),
|
||||||
littleEndianInv(x06 + y06) ~ littleEndianInv(x07 + y07) ~
|
littleEndianInv(x03 + y03),
|
||||||
littleEndianInv(x08 + y08) ~ littleEndianInv(x09 + y09) ~
|
littleEndianInv(x04 + y04),
|
||||||
littleEndianInv(x10 + y10) ~ littleEndianInv(x11 + y11) ~
|
littleEndianInv(x05 + y05),
|
||||||
littleEndianInv(x12 + y12) ~ littleEndianInv(x13 + y13) ~
|
littleEndianInv(x06 + y06),
|
||||||
littleEndianInv(x14 + y14) ~ littleEndianInv(x15 + y15);
|
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[] test0 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
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 = chacha20(test0);
|
test0 = chacha20(test0);
|
||||||
|
|
||||||
ubyte[] test1 = [211,159, 13,115, 76, 55, 82,183, 3,117,222, 37,191,187,234,136,
|
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,
|
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,
|
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];
|
79,201,235, 79, 3, 81,156, 47,203, 26,244,243, 88,118,104, 54];
|
||||||
test1 = chacha20(test1);
|
test1 = chacha20(test1);
|
||||||
|
|
||||||
ubyte[] test2 = [ 88,118,104, 54, 79,201,235, 79, 3, 81,156, 47,203, 26,244,243,
|
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,
|
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,
|
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];
|
238, 55,204, 36, 31,240, 32, 63, 15, 83, 93,161,116,147, 48,113];
|
||||||
test2 = chacha20(test2);
|
test2 = chacha20(test2);
|
||||||
|
|
||||||
ubyte[] test3 = [ 6,124, 83,146, 38,191, 9, 50, 4,161, 47,222,122,182,223,185,
|
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,
|
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,
|
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];
|
94, 94, 99, 52, 90,117, 91,220,146,190,239,143,196,176,130,186];
|
||||||
foreach (i; 0..1000000)
|
foreach (i; 0..1_000_000)
|
||||||
test3 = chacha20(test3);
|
test3 = chacha20(test3);
|
||||||
|
|
||||||
assert(test0 == [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
assert(test0 == [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -286,39 +304,32 @@ unittest
|
||||||
29,214,235,224, 96, 42, 55, 53,188, 35, 81,171, 81,218,221, 44]);
|
29,214,235,224, 96, 42, 55, 53,188, 35, 81,171, 81,218,221, 44]);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ubyte[4] σ0 = [101, 120, 112, 97];
|
static immutable ubyte[4] sigma0 = [101, 120, 112, 97];
|
||||||
enum ubyte[4] σ1 = [110, 100, 32, 51];
|
static immutable ubyte[4] sigma1 = [110, 100, 32, 51];
|
||||||
enum ubyte[4] σ2 = [ 50, 45, 98, 121];
|
static immutable ubyte[4] sigma2 = [ 50, 45, 98, 121];
|
||||||
enum ubyte[4] σ3 = [116, 101, 32, 107];
|
static immutable ubyte[4] sigma3 = [116, 101, 32, 107];
|
||||||
|
|
||||||
|
ubyte[64] chacha20Exp(in ubyte[32] key, in ubyte[16] n) @safe pure nothrow @nogc
|
||||||
|
|
||||||
ubyte[] chacha20Exp(in ubyte[] key, in ubyte[] n) @safe nothrow pure
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
assert(key.length == 32);
|
return chacha20(concat!(ubyte[64])(sigma0,
|
||||||
assert(n.length == 16);
|
key[0..16],
|
||||||
}
|
sigma1,
|
||||||
out(result)
|
n,
|
||||||
{
|
sigma2,
|
||||||
assert(result.length == 64);
|
key[16..$],
|
||||||
}
|
sigma3));
|
||||||
body
|
|
||||||
{
|
|
||||||
return chacha20(σ0 ~ key[0..16] ~ σ1 ~ n ~ σ2 ~ key[16..$] ~ σ3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
ubyte[] key;
|
immutable ubyte[32] key = [ 1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
ubyte[] n;
|
9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
key.length = 32;
|
201,202,203,204,205,206,207,208,
|
||||||
n.length = 16;
|
209,210,211,212,213,214,215,216];
|
||||||
foreach (i; 0..16)
|
|
||||||
key[i] = cast(ubyte)(i + 1);
|
|
||||||
foreach (i; 16..32)
|
|
||||||
key[i] = cast(ubyte)(i + 200 - 15);
|
|
||||||
|
|
||||||
foreach (i; 0..16)
|
immutable ubyte[16] n = [101,102,103,104,105,106,107,108,
|
||||||
n[i] = cast(ubyte)(i + 1+ 100);
|
109,110,111,112,113,114,115,116];
|
||||||
|
|
||||||
assert(chacha20Exp(key, n) == [ 2, 7, 55,183,240,232, 0,145,207,208,120,131,146, 9,130, 31,
|
assert(chacha20Exp(key, n) == [ 2, 7, 55,183,240,232, 0,145,207,208,120,131,146, 9,130, 31,
|
||||||
99,154, 60, 98,194,161,191, 80,167, 61,100,101,173,193, 48,203,
|
99,154, 60, 98,194,161,191, 80,167, 61,100,101,173,193, 48,203,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
module cipher;
|
module cipher;
|
||||||
|
|
||||||
private import std.range : isInputRange, isForwardRange, ElementType,
|
private:
|
||||||
|
|
||||||
|
import std.range : isInputRange, isForwardRange, ElementType,
|
||||||
InputRange, ForwardRange, inputRangeObject;
|
InputRange, ForwardRange, inputRangeObject;
|
||||||
|
import std.string : format;
|
||||||
|
|
||||||
private import std.string : format;
|
import salsa20;
|
||||||
|
import chacha20;
|
||||||
private import salsa20;
|
|
||||||
|
|
||||||
private import chacha20;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
|
||||||
assert(!empty);
|
assert(!empty);
|
||||||
if (++salsaCounter == 64)
|
if (++salsaCounter == 64)
|
||||||
{
|
{
|
||||||
import std.stdio;
|
|
||||||
salsaSection = salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(++count)));
|
salsaSection = salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(++count)));
|
||||||
salsaCounter = 0;
|
salsaCounter = 0;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +57,7 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
|
||||||
return rangeResult(0UL, range, salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(0UL))));
|
return rangeResult(0UL, range, salsa20Exp(key, concat!(ubyte[16])(nonce, littleEndianInv(0UL))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Create more unittest!!!
|
// TODO: Create more unittests!!!
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -144,11 +143,11 @@ enum string rowRound(alias _x00, alias _x01, alias _x02, alias _x03,
|
||||||
mixin(rowRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
mixin(rowRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15));
|
x08, x09, x10, x11, x12, x13, x14, x15));
|
||||||
|
|
||||||
uint[] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
immutable uint[16] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
||||||
y08, y09, y10, y11, y12, y13, y14, y15];
|
y08, y09, y10, y11, y12, y13, y14, y15];
|
||||||
|
|
||||||
uint[] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
immutable uint[16] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15];
|
x08, x09, x10, x11, x12, x13, x14, x15];
|
||||||
|
|
||||||
assert(test0 == [0x08008145, 0x00000080, 0x00010200, 0x20500000,
|
assert(test0 == [0x08008145, 0x00000080, 0x00010200, 0x20500000,
|
||||||
0x20100001, 0x00048044, 0x00000080, 0x00010000,
|
0x20100001, 0x00048044, 0x00000080, 0x00010000,
|
||||||
|
@ -197,11 +196,11 @@ enum string colRound(alias _x00, alias _x01, alias _x02, alias _x03,
|
||||||
mixin(colRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
mixin(colRound!(x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15));
|
x08, x09, x10, x11, x12, x13, x14, x15));
|
||||||
|
|
||||||
immutable uint[] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
immutable uint[16] test0 = [y00, y01, y02, y03, y04, y05, y06, y07,
|
||||||
y08, y09, y10, y11, y12, y13, y14, y15];
|
y08, y09, y10, y11, y12, y13, y14, y15];
|
||||||
|
|
||||||
immutable uint[] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
immutable uint[16] test1 = [x00, x01, x02, x03, x04, x05, x06, x07,
|
||||||
x08, x09, x10, x11, x12, x13, x14, x15];
|
x08, x09, x10, x11, x12, x13, x14, x15];
|
||||||
|
|
||||||
assert(test0 == [0x10090288, 0x00000000, 0x00000000, 0x00000000,
|
assert(test0 == [0x10090288, 0x00000000, 0x00000000, 0x00000000,
|
||||||
0x00000101, 0x00000000, 0x00000000, 0x00000000,
|
0x00000101, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
@ -281,7 +280,7 @@ ubyte[64] salsa20(in ubyte[64] input) pure nothrow @safe @nogc
|
||||||
75, 27, 0,216, 16,122, 7, 89,162,104,101,147,213, 21, 54, 95,
|
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,
|
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];
|
94, 94, 99, 52, 90,117, 91,220,146,190,239,143,196,176,130,186];
|
||||||
foreach (i; 0..1000000)
|
foreach (i; 0..1_000_000)
|
||||||
test3 = salsa20(test3);
|
test3 = salsa20(test3);
|
||||||
|
|
||||||
assert(test0 == [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
assert(test0 == [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -310,7 +309,7 @@ static immutable ubyte[4] sigma1 = [110, 100, 32, 51];
|
||||||
static immutable ubyte[4] sigma2 = [ 50, 45, 98, 121];
|
static immutable ubyte[4] sigma2 = [ 50, 45, 98, 121];
|
||||||
static immutable ubyte[4] sigma3 = [116, 101, 32, 107];
|
static immutable ubyte[4] sigma3 = [116, 101, 32, 107];
|
||||||
|
|
||||||
ubyte[64] salsa20Exp(in ubyte[32] key, in ubyte[16] n) @safe pure nothrow @nogc
|
ubyte[64] salsa20Exp(in ref ubyte[32] key, in ubyte[16] n) @safe pure nothrow @nogc
|
||||||
{
|
{
|
||||||
return salsa20(concat!(ubyte[64])(sigma0,
|
return salsa20(concat!(ubyte[64])(sigma0,
|
||||||
key[0..16],
|
key[0..16],
|
||||||
|
@ -323,15 +322,13 @@ ubyte[64] salsa20Exp(in ubyte[32] key, in ubyte[16] n) @safe pure nothrow @nogc
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
ubyte[32] key;
|
immutable ubyte[32] key = [ 1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
ubyte[16] n;
|
9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
foreach (i; 0..16)
|
201,202,203,204,205,206,207,208,
|
||||||
key[i] = cast(ubyte)(i + 1);
|
209,210,211,212,213,214,215,216];
|
||||||
foreach (i; 16..32)
|
|
||||||
key[i] = cast(ubyte)(i + 200 - 15);
|
|
||||||
|
|
||||||
foreach (i; 0..16)
|
immutable ubyte[16] n = [101,102,103,104,105,106,107,108,
|
||||||
n[i] = cast(ubyte)(i + 1 + 100);
|
109,110,111,112,113,114,115,116];
|
||||||
|
|
||||||
assert(salsa20Exp(key, n) == [ 69, 37, 68, 39, 41, 15,107,193,255,139,122, 6,170,233,217, 98,
|
assert(salsa20Exp(key, n) == [ 69, 37, 68, 39, 41, 15,107,193,255,139,122, 6,170,233,217, 98,
|
||||||
89,144,182,106, 21, 51,200, 65,239, 49,222, 34,215,114, 40,126,
|
89,144,182,106, 21, 51,200, 65,239, 49,222, 34,215,114, 40,126,
|
||||||
|
|
|
@ -12,3 +12,16 @@ auto concat(T : E[n], E, size_t n)(in E[][] args...) @nogc
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
assert(concat!(int[0])() == []);
|
||||||
|
assert(concat!(int[0])([]) == []);
|
||||||
|
assert(concat!(int[0])([], []) == []);
|
||||||
|
assert(concat!(int[1])([1]) == [1]);
|
||||||
|
assert(concat!(int[1])([1], []) == [1]);
|
||||||
|
assert(concat!(int[1])([], [1]) == [1]);
|
||||||
|
assert(concat!(int[2])([1, 2]) == [1, 2]);
|
||||||
|
assert(concat!(int[2])([1], [2]) == [1, 2]);
|
||||||
|
assert(concat!(int[6])([1], [2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6]);
|
||||||
|
assert(concat!(char[12])("Hello", " ", "World!") == "Hello World!");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue