Initiliazation
This commit is contained in:
416
full/Angel-payload/angel/utils/cryptography/bitmanip.d
Normal file
416
full/Angel-payload/angel/utils/cryptography/bitmanip.d
Normal file
@@ -0,0 +1,416 @@
|
||||
module angel.utils.cryptography.bitmanip;
|
||||
|
||||
import std.traits;
|
||||
///
|
||||
/// This module contains several methods to convert integer types into byte arrays
|
||||
/// and vice versa.
|
||||
///
|
||||
///
|
||||
|
||||
alias rotateLeft rol;
|
||||
alias rotateRight ror;
|
||||
|
||||
/// rot shift to the left
|
||||
/// Params:
|
||||
/// x = integer to shift
|
||||
/// shiftAmount = number of bits to shift
|
||||
@safe
|
||||
@nogc
|
||||
T rotateLeft(T)(T x, uint shiftAmount) pure nothrow
|
||||
{
|
||||
enum nbits = T.sizeof*8;
|
||||
//shiftAmount %= nbits;
|
||||
return cast(T)(x << shiftAmount) | (x >>> (nbits-shiftAmount));
|
||||
}
|
||||
|
||||
/// test rotateLeft
|
||||
unittest {
|
||||
ubyte b0 = 0b10000001;
|
||||
ubyte b1 = 0b00000011;
|
||||
ubyte b2 = 0b00000110;
|
||||
ubyte b7 = 0b11000000;
|
||||
|
||||
assert(rotateLeft(b0,0) == b0);
|
||||
assert(rotateLeft(b0,1) == b1);
|
||||
assert(rotateLeft(b0,2) == b2);
|
||||
assert(rotateLeft(b0,7) == b7);
|
||||
assert(rotateLeft(b0,8) == b0);
|
||||
}
|
||||
|
||||
/// rot shift to the right
|
||||
/// Params:
|
||||
/// x = integer to shift
|
||||
/// shiftAmount = number of bits to shift
|
||||
@safe
|
||||
@nogc
|
||||
T rotateRight(T)(T x, uint shiftAmount) pure nothrow
|
||||
{
|
||||
enum nbits = T.sizeof*8;
|
||||
//shiftAmount %= nbits;
|
||||
return cast(T)((x >>> shiftAmount) | (x << (nbits-shiftAmount)));
|
||||
}
|
||||
|
||||
/// test rotateRight
|
||||
unittest {
|
||||
ubyte b0 = 0b00000101;
|
||||
ubyte b1 = 0b10000010;
|
||||
ubyte b2 = 0b01000001;
|
||||
ubyte b7 = 0b00001010;
|
||||
|
||||
assert(rotateRight(b0,0) == b0);
|
||||
assert(rotateRight(b0,1) == b1);
|
||||
assert(rotateRight(b0,2) == b2);
|
||||
assert(rotateRight(b0,7) == b7);
|
||||
assert(rotateRight(b0,8) == b0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Converts big endian bytes to integral of type T
|
||||
Params: bs = the big endian bytes
|
||||
Returns: integral of type T
|
||||
*/
|
||||
@safe @nogc
|
||||
T fromBigEndian(T)(in ubyte[] bs) if (isIntegral!T)
|
||||
in {
|
||||
assert(bs.length >= T.sizeof, "input buffer too short");
|
||||
}
|
||||
body {
|
||||
version(BigEndian) {
|
||||
// data is already in memory as we want
|
||||
return (cast(const T[])bs)[0];
|
||||
}else {
|
||||
Unqual!T n = 0;
|
||||
static if (T.sizeof >= short.sizeof) {
|
||||
n |= bs[0];
|
||||
n <<= 8;
|
||||
n |= bs[1];
|
||||
}
|
||||
static if (T.sizeof >= int.sizeof) {
|
||||
n <<= 8;
|
||||
n |= bs[2];
|
||||
n <<= 8;
|
||||
n |= bs[3];
|
||||
}
|
||||
static if (T.sizeof == long.sizeof) {
|
||||
n <<= 8;
|
||||
n |= bs[4];
|
||||
n <<= 8;
|
||||
n |= bs[5];
|
||||
n <<= 8;
|
||||
n |= bs[6];
|
||||
n <<= 8;
|
||||
n |= bs[7];
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Converts little endian bytes to integral of type T
|
||||
Params: bs = the little endian bytes
|
||||
Returns: integral of type T
|
||||
*/
|
||||
@safe @nogc
|
||||
T fromLittleEndian(T)(in ubyte[] bs) if (isIntegral!T)
|
||||
in {
|
||||
assert(bs.length >= T.sizeof, "input buffer too short");
|
||||
}
|
||||
body {
|
||||
version(LittleEndian) {
|
||||
// data is already in memory as we want
|
||||
return (cast(const T[])bs)[0];
|
||||
}else {
|
||||
Unqual!T n = 0;
|
||||
static if (T.sizeof >= short.sizeof) {
|
||||
n |= bs[0];
|
||||
n |= cast(T)bs[1] << 8;
|
||||
}
|
||||
static if (T.sizeof >= int.sizeof) {
|
||||
n |= cast(T)bs[2] << 16;
|
||||
n |= cast(T)bs[3] << 24;
|
||||
}
|
||||
static if (T.sizeof == long.sizeof) {
|
||||
n |= cast(T)bs[4] << 32;
|
||||
n |= cast(T)bs[5] << 40;
|
||||
n |= cast(T)bs[6] << 48;
|
||||
n |= cast(T)bs[7] << 56;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Converts big endian bytes to integrals of type T
|
||||
size of bs has to match the size in bytes of output
|
||||
Params:
|
||||
bs = the big endian bytes
|
||||
output = where the T's get written to
|
||||
*/
|
||||
@safe @nogc
|
||||
void fromBigEndian(T)(in ubyte[] bs, T[] output) if (isIntegral!T)
|
||||
in {
|
||||
assert(bs.length == output.length * T.sizeof, "size of input array does not match size of output array");
|
||||
}
|
||||
body {
|
||||
version(BigEndian) {
|
||||
// short cut on big endian systems
|
||||
const T[] casted = cast(const T[]) bs;
|
||||
output[] = casted[];
|
||||
} else {
|
||||
// for little endian systems
|
||||
enum s = T.sizeof;
|
||||
foreach (i; 0 .. output.length)
|
||||
{
|
||||
output[i] = fromBigEndian!T(bs[s*i .. s*i+s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Converts little endian bytes to integrals of type T
|
||||
size of bs has to match the size in bytes of output
|
||||
Params:
|
||||
bs = the little endian bytes
|
||||
output = where the T's get written to
|
||||
*/
|
||||
@safe @nogc
|
||||
void fromLittleEndian(T)(in ubyte[] bs, T[] output) if (isIntegral!T)
|
||||
in {
|
||||
assert(bs.length == output.length * T.sizeof, "size of input array does not match size of output array");
|
||||
}
|
||||
body {
|
||||
version(LittleEndian) {
|
||||
// short cut on little endian systems
|
||||
const T[] casted = cast(const T[]) bs;
|
||||
output[] = casted[];
|
||||
} else {
|
||||
// for big endian systems
|
||||
enum s = T.sizeof;
|
||||
foreach (i; 0 .. output.length)
|
||||
{
|
||||
output[i] = fromLittleEndian!T(bs[s*i .. s*i+s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
convert a integral type T into an array of bytes.
|
||||
Params:
|
||||
n = the number
|
||||
output = the buffer to write the bytes to
|
||||
*/
|
||||
@safe @nogc
|
||||
void toBigEndian(T)(in T val, ubyte[] output) if(isIntegral!T)
|
||||
in {
|
||||
assert(output.length >= T.sizeof, "output buffer too small");
|
||||
}
|
||||
body {
|
||||
Unqual!T n = val;
|
||||
uint off = 0;
|
||||
|
||||
static if(T.sizeof == long.sizeof) {
|
||||
output[off] = cast (ubyte) (n >>> 56);
|
||||
++off;
|
||||
output[off] = cast (ubyte) (n >>> 48);
|
||||
++off;
|
||||
output[off] = cast (ubyte) (n >>> 40);
|
||||
++off;
|
||||
output[off] = cast (ubyte) (n >>> 32);
|
||||
++off;
|
||||
}
|
||||
static if(T.sizeof >= int.sizeof) {
|
||||
output[off] = cast (ubyte) (n >>> 24);
|
||||
++off;
|
||||
output[off] = cast (ubyte) (n >>> 16);
|
||||
++off;
|
||||
}
|
||||
static if(T.sizeof >= short.sizeof) {
|
||||
output[off] = cast (ubyte) (n >>> 8);
|
||||
++off;
|
||||
}
|
||||
output[off] = cast (ubyte) (n);
|
||||
}
|
||||
|
||||
/**
|
||||
convert a integral type T into an array of bytes.
|
||||
Params:
|
||||
n = the number
|
||||
output = the buffer to write the bytes to
|
||||
*/
|
||||
@safe @nogc
|
||||
void toLittleEndian(T)(in T val, ubyte[] output) if(isIntegral!T)
|
||||
in {
|
||||
assert(output.length >= T.sizeof, "output buffer too small");
|
||||
}
|
||||
body {
|
||||
Unqual!T n = val;
|
||||
output[0] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
static if(T.sizeof >= short.sizeof) {
|
||||
output[1] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
}
|
||||
static if(T.sizeof >= int.sizeof) {
|
||||
output[2] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
output[3] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
}
|
||||
static if(T.sizeof == long.sizeof) {
|
||||
output[4] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
output[5] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
output[6] = cast (ubyte) (n);
|
||||
n >>>= 8;
|
||||
output[7] = cast (ubyte) (n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
convert a integral type T[] into an array of bytes.
|
||||
Params:
|
||||
ns = the numbers
|
||||
output = the buffer to write the bytes to
|
||||
*/
|
||||
@safe @nogc
|
||||
void toBigEndian(T)(in T[] ns, ubyte[] output) if(isIntegral!T)
|
||||
in {
|
||||
assert(output.length >= T.sizeof*ns.length, "output buffer too small");
|
||||
}
|
||||
body {
|
||||
version(BigEndian) {
|
||||
// shortcut on BigEndian systems
|
||||
const ubyte[] casted = cast(const ubyte []) ns;
|
||||
output[] = casted[];
|
||||
}else{
|
||||
foreach(i, const T n; ns) {
|
||||
toBigEndian!T(n, output[T.sizeof * i .. $]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
convert a integral type T[] into an array of bytes.
|
||||
Params:
|
||||
ns the numbers
|
||||
output the buffer to write the bytes to
|
||||
*/
|
||||
@safe @nogc
|
||||
void toLittleEndian(T)(in T[] ns, ubyte[] output) if(isIntegral!T)
|
||||
in {
|
||||
assert(output.length >= T.sizeof*ns.length, "output buffer too small");
|
||||
}
|
||||
body {
|
||||
version(LittleEndian) {
|
||||
// shortcut on LittleEndian systems
|
||||
const ubyte[] casted = cast(const ubyte []) ns;
|
||||
output[] = casted[];
|
||||
}else{
|
||||
foreach(i, const T n; ns) {
|
||||
toLittleEndian!T(n, output[T.sizeof * i .. $]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ubyte[T.sizeof] toBigEndian(T)(in T n) pure nothrow @nogc
|
||||
if(isIntegral!T)
|
||||
{
|
||||
ubyte[T.sizeof] bs;
|
||||
toBigEndian!T(n, bs);
|
||||
return bs;
|
||||
}
|
||||
|
||||
ubyte[] toBigEndian(T)(in T[] ns) if(isIntegral!T)
|
||||
{
|
||||
ubyte[] bs = new ubyte[T.sizeof * ns.length];
|
||||
toBigEndian!T(ns, bs);
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
ubyte[T.sizeof] toLittleEndian(T)(in T n) pure nothrow @nogc
|
||||
if(isIntegral!T)
|
||||
{
|
||||
ubyte[T.sizeof] bs;
|
||||
toLittleEndian!T(n, bs);
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
ubyte[] toLittleEndian(T)(in T[] ns) if(isIntegral!T)
|
||||
{
|
||||
ubyte[] bs = new ubyte[T.sizeof * ns.length];
|
||||
toLittleEndian!T(ns, bs);
|
||||
return bs;
|
||||
}
|
||||
|
||||
unittest {
|
||||
|
||||
// int
|
||||
assert(toBigEndian(0x01020304) == [0x01,0x02,0x03,0x04], "intToBigEndian failed");
|
||||
assert(toLittleEndian(0x01020304) == [0x04,0x03,0x02,0x01], "intToLittleEndian failed");
|
||||
|
||||
|
||||
// long
|
||||
assert(toBigEndian(0x0102030405060708L) == [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08], "longToBigEndian failed");
|
||||
assert(toLittleEndian(0x0807060504030201L) == [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08], "longToLittleEndian failed");
|
||||
|
||||
// bigEndian to short, int, long
|
||||
assert(fromBigEndian!ushort([0x01,0x02]) == 0x0102u);
|
||||
assert(fromBigEndian!uint([0x01,0x02,0x03,0x04]) == 0x01020304u);
|
||||
assert(fromBigEndian!ulong([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08]) == 0x0102030405060708UL);
|
||||
|
||||
// littleEndian to short, int, long
|
||||
assert(fromLittleEndian!ushort([0x02,0x01]) == 0x0102u);
|
||||
assert(fromLittleEndian!uint([0x04,0x03,0x02,0x01]) == 0x01020304u);
|
||||
assert(fromLittleEndian!ulong([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08]) == 0x0807060504030201UL);
|
||||
|
||||
// bigEndian: convert multiple ints
|
||||
uint[] output = new uint[2];
|
||||
immutable ubyte[] input = [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08];
|
||||
fromBigEndian(input, output);
|
||||
assert(output == [0x01020304u, 0x05060708u], "fromBigEndian(ubyte[] input, int[] output) failed");
|
||||
|
||||
// littleEndian: convert multiple ints
|
||||
output = new uint[2];
|
||||
fromLittleEndian(input, output);
|
||||
assert(output == [0x04030201u, 0x08070605u], "fromLittleEndian(ubyte[] input, int[] output) failed");
|
||||
|
||||
|
||||
immutable int i = 0xf1f2f3f4;
|
||||
int iResult;
|
||||
ubyte[] buf;
|
||||
|
||||
// int to bigEndian
|
||||
buf = new ubyte[4];
|
||||
toBigEndian!int(i, buf);
|
||||
iResult = fromBigEndian!int(buf);
|
||||
assert(i == iResult);
|
||||
|
||||
// int to littleEndian
|
||||
buf = new ubyte[4];
|
||||
toLittleEndian!int(i, buf);
|
||||
iResult = fromLittleEndian!int(buf);
|
||||
assert(i == iResult);
|
||||
|
||||
|
||||
|
||||
immutable long l = 0xf1f2f3f4f5f6f7f8;
|
||||
long lResult;
|
||||
|
||||
// long to bigEndian
|
||||
buf = new ubyte[8];
|
||||
toBigEndian!long(l, buf);
|
||||
lResult = fromBigEndian!long(buf);
|
||||
assert(l == lResult);
|
||||
|
||||
// int to littleEndian
|
||||
buf = new ubyte[8];
|
||||
toLittleEndian!long(l, buf);
|
||||
lResult = fromLittleEndian!long(buf);
|
||||
assert(l == lResult);
|
||||
}
|
||||
Reference in New Issue
Block a user