Moved bit-rotation functions to a separate module and fixed 'statement not reachable' warnings

This commit is contained in:
Johannes Loher 2016-02-14 12:01:00 +01:00
parent 826aad7786
commit a2ea77f667
4 changed files with 46 additions and 22 deletions

37
source/bitmanip.d Normal file
View file

@ -0,0 +1,37 @@
module bitmanip;
private import std.traits : isUnsigned;
UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure
if(isUnsigned!UIntType)
{
auto reducedLen = len % (8 * UIntType.sizeof);
// TODO: ensure the compiler does not create different code paths here
return cast(UIntType)((val << reducedLen) | (val >> (8 * UIntType.sizeof - reducedLen)));
}
unittest
{
ubyte[] test = [0, 1, 128];
assert(test[0].rotateLeft(1) == 0);
assert(test[1].rotateLeft(1) == 2);
assert(test[2].rotateLeft(1) == 1);
assert(test[1].rotateLeft(7) == 128);
}
UIntType rotateRight(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure
if(isUnsigned!UIntType)
{
auto reducedLen = len % (8 * UIntType.sizeof);
// TODO: ensure the compiler does not create different code paths here
return cast(UIntType)((val >> reducedLen) | (val << (8 * UIntType.sizeof - reducedLen)));
}
unittest
{
ubyte[] test = [0, 1, 128];
assert(test[0].rotateRight(1) == 0);
assert(test[1].rotateRight(1) == 128);
assert(test[2].rotateRight(1) == 64);
assert(test[2].rotateRight(7) == 1);
}

View file

@ -1,11 +1,12 @@
module chacha20;
private import std.traits : isUnsigned;
private import std.string : format;
private import std.range : isInputRange, isForwardRange, ElementType;
private import std.bitmanip : nativeToLittleEndian, littleEndianToNative;
private import std.array;
private import bitmanip;
public:
// TODO: Create unittests!!!!
@ -72,14 +73,6 @@ auto chacha20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
private:
UIntType rotateLeft(UIntType)(in UIntType val, in size_t len) nothrow @nogc pure
if(isUnsigned!UIntType)
{
auto reducedLen = len % (8 * UIntType.sizeof);
// TODO: ensure the compiler does not create different code paths here
return cast(UIntType)((val << reducedLen) | (val >> (8 * UIntType.sizeof - reducedLen)));
}
enum string quarterRound(alias _x0, alias _x1, alias _x2, alias _x3) = q{
%1$s += %2$s; %4$s ^= %1$s; %4$s = rotateLeft(%4$s, 16);
%3$s += %4$s; %2$s ^= %3$s; %2$s = rotateLeft(%2$s, 12);
@ -228,7 +221,7 @@ in
}
body
{
ubyte buf[uint.sizeof] = input;
ubyte[uint.sizeof] buf = input;
return littleEndianToNative!uint(buf);
}

View file

@ -3,10 +3,12 @@ module cipher;
private import std.range : isInputRange, ElementType;
private import salsa20;
private import chacha20;
import std.stdio;
public:
enum Cipher {
enum Cipher
{
salsa20,
chacha20
}
@ -18,10 +20,8 @@ auto cipherFunction(R)(R range, ubyte[32] key, ubyte[8] nonce, Cipher cipher)
{
case Cipher.salsa20:
return salsa20Cipher(range, key, nonce);
break;
case Cipher.chacha20:
return salsa20Cipher(range, key, nonce);
break;
}
}

View file

@ -6,6 +6,8 @@ private import std.range : isInputRange, isForwardRange, ElementType;
private import std.bitmanip : nativeToLittleEndian, littleEndianToNative;
private import std.array;
private import bitmanip;
public:
auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
@ -70,14 +72,6 @@ auto salsa20Cipher(R)(R range, ubyte[32] key, ubyte[8] nonce)
private:
UIntType rotateLeft(UIntType)(in UIntType val, in size_t len)
if(isUnsigned!UIntType)
{
auto reducedLen = len % (8 * UIntType.sizeof);
// TODO: ensure the compiler does not create different code paths here
return cast(UIntType)((val << reducedLen) | (val >> (8 * UIntType.sizeof - reducedLen)));
}
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);
@ -227,7 +221,7 @@ in
}
body
{
ubyte buf[uint.sizeof] = input;
ubyte[uint.sizeof] buf = input;
return littleEndianToNative!uint(buf);
}