From 62ccd373ab66fa44ec896f0a19b6674d7a697920 Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Sat, 24 Sep 2016 15:37:40 +0200 Subject: [PATCH] Fixed some endianess stuff and added bufferedChunks function --- source/bitmanip.d | 25 +------ source/chacha20.d | 3 +- source/salsa20.d | 38 +++++----- source/utility.d | 182 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 203 insertions(+), 45 deletions(-) diff --git a/source/bitmanip.d b/source/bitmanip.d index c4d36ea..98470fe 100644 --- a/source/bitmanip.d +++ b/source/bitmanip.d @@ -2,7 +2,7 @@ module bitmanip; private import std.traits : isUnsigned; -private import std.bitmanip : nativeToLittleEndian, littleEndianToNative, nativeToBigEndian, bigEndianToNative; +private import std.bitmanip : nativeToLittleEndian, littleEndianToNative; UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure @safe if (isUnsigned!UIntType) @@ -48,26 +48,3 @@ body ubyte[uint.sizeof] buf = input; return littleEndianToNative!uint(buf); } - -alias bigEndianInv = nativeToBigEndian; - -uint bigEndian(in ubyte[] input) @safe pure nothrow @nogc -in -{ - assert(input.length == uint.sizeof); -} -body -{ - ubyte[uint.sizeof] buf = input; - return bigEndianToNative!uint(buf); -} - -unittest -{ - ubyte[] test0 = [0, 0, 0, 0]; - ubyte[] test1 = [86, 75, 30, 9]; - ubyte[] test2 = [255, 255, 255, 250]; - assert(littleEndian(test0) == 0x00000000); - assert(littleEndian(test1) == 0x091e4b56); - assert(littleEndian(test2) == 0xfaffffff); -} diff --git a/source/chacha20.d b/source/chacha20.d index 4437f0f..8e18ab7 100644 --- a/source/chacha20.d +++ b/source/chacha20.d @@ -40,7 +40,8 @@ auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) assert(!empty); if (++chachaCounter == 64) { - chachaSection = chacha20Exp(key, concat!(ubyte[16])(bigEndianInv(++count), nonce)); + chachaSection = chacha20Exp(key, + concat!(ubyte[16])(littleEndianInv(++count), nonce)); chachaCounter = 0; } range.popFront(); diff --git a/source/salsa20.d b/source/salsa20.d index f9f3367..91f47e1 100644 --- a/source/salsa20.d +++ b/source/salsa20.d @@ -41,7 +41,7 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce) if (++salsaCounter == 64) { salsaSection = salsa20Exp(key, concat!(ubyte[16])(nonce, - bigEndianInv(++count))); + littleEndianInv(++count))); salsaCounter = 0; } range.popFront(); @@ -81,9 +81,9 @@ enum string quarterRound(alias _x0, alias _x1, alias _x2, alias _x3) = q{ %2$s ^= (%1$s + %4$s).rotateLeft(7); %3$s ^= (%2$s + %1$s).rotateLeft(9); %4$s ^= (%3$s + %2$s).rotateLeft(13); - %1$s ^= (%4$s + %3$s).rotateLeft(18); -}.format(__traits(identifier, _x0), - __traits(identifier, _x1), __traits(identifier, _x2), __traits(identifier, _x3)); + %1$s ^= (%4$s + %3$s).rotateLeft(18);} + .format(__traits(identifier, _x0), + __traits(identifier, _x1), __traits(identifier, _x2), __traits(identifier, _x3)); @safe unittest { @@ -117,14 +117,13 @@ enum string rowRound(alias _x00, alias _x01, alias _x02, alias _x03, alias _x04, mixin(quarterRound!(%1$s, %2$s, %3$s, %4$s)); mixin(quarterRound!(%6$s, %7$s, %8$s, %5$s)); mixin(quarterRound!(%11$s, %12$s, %9$s, %10$s)); - mixin(quarterRound!(%16$s, %13$s, %14$s, %15$s)); -}.format( - __traits(identifier, _x00), __traits(identifier, - _x01), __traits(identifier, _x02), __traits(identifier, _x03), - __traits(identifier, _x04), __traits(identifier, _x05), __traits(identifier, _x06), - __traits(identifier, _x07), __traits(identifier, _x08), __traits(identifier, _x09), - __traits(identifier, _x10), __traits(identifier, _x11), __traits(identifier, _x12), - __traits(identifier, _x13), __traits(identifier, _x14), __traits(identifier, _x15)); + mixin(quarterRound!(%16$s, %13$s, %14$s, %15$s));} + .format(__traits(identifier, _x00), __traits(identifier, _x01), + __traits(identifier, _x02), __traits(identifier, _x03), __traits(identifier, _x04), + __traits(identifier, _x05), __traits(identifier, _x06), __traits(identifier, _x07), + __traits(identifier, _x08), __traits(identifier, _x09), __traits(identifier, _x10), + __traits(identifier, _x11), __traits(identifier, _x12), __traits(identifier, + _x13), __traits(identifier, _x14), __traits(identifier, _x15)); @safe unittest { @@ -167,14 +166,13 @@ enum string colRound(alias _x00, alias _x01, alias _x02, alias _x03, alias _x04, mixin(quarterRound!(%1$s, %5$s, %9$s, %13$s)); mixin(quarterRound!(%6$s, %10$s, %14$s, %2$s)); mixin(quarterRound!(%11$s, %15$s, %3$s, %7$s)); - mixin(quarterRound!(%16$s, %4$s, %8$s, %12$s)); -}.format( - __traits(identifier, _x00), __traits(identifier, - _x01), __traits(identifier, _x02), __traits(identifier, _x03), - __traits(identifier, _x04), __traits(identifier, _x05), __traits(identifier, _x06), - __traits(identifier, _x07), __traits(identifier, _x08), __traits(identifier, _x09), - __traits(identifier, _x10), __traits(identifier, _x11), __traits(identifier, _x12), - __traits(identifier, _x13), __traits(identifier, _x14), __traits(identifier, _x15)); + mixin(quarterRound!(%16$s, %4$s, %8$s, %12$s));} + .format(__traits(identifier, _x00), __traits(identifier, _x01), + __traits(identifier, _x02), __traits(identifier, _x03), __traits(identifier, _x04), + __traits(identifier, _x05), __traits(identifier, _x06), __traits(identifier, _x07), + __traits(identifier, _x08), __traits(identifier, _x09), __traits(identifier, _x10), + __traits(identifier, _x11), __traits(identifier, _x12), __traits(identifier, + _x13), __traits(identifier, _x14), __traits(identifier, _x15)); @safe unittest { diff --git a/source/utility.d b/source/utility.d index 225bcf2..9a4789d 100644 --- a/source/utility.d +++ b/source/utility.d @@ -1,5 +1,8 @@ module utility; +private import std.range : isInputRange, isInfinite, isForwardRange, + ElementType; + auto concat(T : E[n], E, size_t n)(in E[][] args...) @nogc { size_t offset = 0; @@ -26,3 +29,182 @@ auto concat(T : E[n], E, size_t n)(in E[][] args...) @nogc assert(concat!(int[6])([1], [2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6]); assert(concat!(char[12])("Hello", " ", "World!") == "Hello World!"); } + +auto bufferedChunks(Source)(Source source, size_t chunkSize) + if (isInputRange!Source) +{ + static struct BufferedChunks + { + this(Source source, size_t chunkSize) + { + assert(chunkSize != 0, "Cannot create a Chunk with an empty chunkSize"); + this.source = source; + this.chunkSize = chunkSize; + buffer.length = chunkSize; + foreach (i; 0 .. chunkSize) + { + if (!this.source.empty) + { + buffer[i] = this.source.front; + this.source.popFront; + bufferLength++; + } + else + break; + } + } + + auto front() @property + { + assert(!empty); + return buffer[0 .. bufferLength]; + } + + void popFront() + { + assert(!empty); + bufferLength = 0; + if (!source.empty) + { + foreach (i; 0 .. chunkSize) + { + if (!source.empty) + { + buffer[i] = source.front; + source.popFront; + bufferLength++; + } + else + break; + } + } + } + + static if (isInfinite!Source) + { + enum empty = false; + } + else + { + bool empty() @property + { + return bufferLength == 0; + } + } + + static if (isForwardRange!Source) + { + auto save() + { + auto ret = this; + ret.source = source.save; + ret.buffer = buffer.dup; + return ret; + } + } + + private: + Source source; + size_t chunkSize; + ElementType!Source[] buffer; + size_t bufferLength; + } + + return BufferedChunks(source, chunkSize); +} + +version (unittest) private import std.array; + +@safe unittest +{ + int[] testArray; + auto _bufferedChunks = bufferedChunks(testArray, 1); + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + int[] testArray; + auto _bufferedChunks = bufferedChunks(testArray, 2); + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0], 1); + assert(_bufferedChunks.front == [0]); + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0], 2); + assert(_bufferedChunks.front == [0]); + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0, 1], 1); + assert(_bufferedChunks.front == [0]); + _bufferedChunks.popFront; + assert(_bufferedChunks.front == [1]); + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0, 1], 2); + assert(_bufferedChunks.front == [0, 1]); + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0, 1, 2], 2); + assert(_bufferedChunks.front == [0, 1]); + _bufferedChunks.popFront; + assert(_bufferedChunks.front == [2]); + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0, 1, 2, 3], 2); + assert(_bufferedChunks.front == [0, 1]); + _bufferedChunks.popFront; + assert(_bufferedChunks.front == [2, 3]); + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); +} + +@system unittest +{ + import std.exception : assertThrown; + import core.exception : AssertError; + + assertThrown!AssertError(bufferedChunks([0], 0)); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0], 1); + auto otherBufferedChunks = _bufferedChunks.save; + _bufferedChunks.popFront; + assert(_bufferedChunks.empty); + assert(otherBufferedChunks.front == [0]); +} + +@safe unittest +{ + auto _bufferedChunks = bufferedChunks([0, 1], 1); + auto otherBufferedChunks = _bufferedChunks.save; + _bufferedChunks.popFront; + assert(_bufferedChunks.front == [1]); + assert(otherBufferedChunks.front == [0]); +}