Initiliazation
This commit is contained in:
331
full/Angel-payload/angel/utils/cryptography/gcm/galoisfield.d
Normal file
331
full/Angel-payload/angel/utils/cryptography/gcm/galoisfield.d
Normal file
@@ -0,0 +1,331 @@
|
||||
module angel.utils.cryptography.gcm.galoisfield;
|
||||
|
||||
import std.traits: isIntegral;
|
||||
import std.array;
|
||||
|
||||
package:
|
||||
@safe
|
||||
struct GF128
|
||||
{
|
||||
|
||||
alias ubyte T;
|
||||
alias T[BLOCKLEN/(T.sizeof*8)] block;
|
||||
|
||||
enum BLOCKLEN = 128;
|
||||
|
||||
enum T R = 0xE1<<(T.sizeof*8-8);
|
||||
|
||||
enum T ONE = 0x80<<(T.sizeof*8-8);
|
||||
|
||||
/**
|
||||
* raises x to the power 'pow' by squaring
|
||||
* x <- x^pow
|
||||
*
|
||||
* Params:
|
||||
* x = this value gets raised to the power pow
|
||||
* pow = the power
|
||||
*/
|
||||
static void power(T)(T[] x, ulong pow) nothrow @nogc
|
||||
if(isIntegral!T)
|
||||
in {
|
||||
assert(x.length*T.sizeof*8 == BLOCKLEN, "invalid length. expected 16 bytes.");
|
||||
}
|
||||
body {
|
||||
block squared;
|
||||
squared[] = x[];
|
||||
|
||||
block exp;
|
||||
exp[0] = ONE; // little endian 1
|
||||
|
||||
block one;
|
||||
one[0] = ONE; // little endian 1
|
||||
|
||||
while(pow > 0) {
|
||||
|
||||
if(pow & 0x1) {
|
||||
multiply(exp, squared);
|
||||
} else {
|
||||
multiply(exp, one); // dummy multiplication to avoid timing attacks
|
||||
}
|
||||
|
||||
multiply(squared, squared);
|
||||
|
||||
pow = pow >> 1;
|
||||
}
|
||||
|
||||
x[] = exp[];
|
||||
}
|
||||
|
||||
// test power
|
||||
unittest {
|
||||
immutable ubyte[] x = cast(immutable ubyte[]) x"66e94bd4ef8a2c3b884cfa59ca342b2e";
|
||||
|
||||
ubyte[16] naivePow;
|
||||
naivePow[0] = 0x80; // little endian 1
|
||||
|
||||
immutable uint pow = 13;
|
||||
|
||||
for(uint i = 0; i < pow; ++i) {
|
||||
multiply(naivePow, x);
|
||||
}
|
||||
|
||||
ubyte[16] powBySquare;
|
||||
powBySquare[] = x[];
|
||||
|
||||
power(powBySquare, pow);
|
||||
|
||||
assert(naivePow == powBySquare, "power() failed");
|
||||
}
|
||||
|
||||
/// Multiplies x by y using schoolbook multiplication. Result stored in x.
|
||||
static void multiply(T[] x, in T[] y) nothrow @nogc
|
||||
in {
|
||||
assert(x.length*T.sizeof*8 == BLOCKLEN, "x: invalid length.");
|
||||
}
|
||||
body {
|
||||
|
||||
block v = x;
|
||||
block z;
|
||||
|
||||
for(uint i = 0; i < y.length; ++i) {
|
||||
T currWord = y[i];
|
||||
|
||||
for(int j = T.sizeof*8-1; j >= 0; --j) {
|
||||
|
||||
// if((currWord >> j) & 0x01) {
|
||||
// z[] ^= v[];
|
||||
// }
|
||||
// avoid branching:
|
||||
//z[] ^= v[]&(-(cast(T)((currWord >> j) & 1)));
|
||||
z[] ^= v[] & cast(T)(-cast(int)((currWord >> j) & 1)); // less prone to timing attacks than if statement
|
||||
|
||||
T lsb = v[$-1] & 1;
|
||||
shiftRight(v);
|
||||
|
||||
// if(lsb) {
|
||||
// v[0] ^= R;
|
||||
// }
|
||||
// Avoid branching by using conditional XOR:
|
||||
v[0] ^= R&(-lsb); // -lsb is either 0x00, or 0xFF
|
||||
}
|
||||
}
|
||||
|
||||
x[] = z[];
|
||||
}
|
||||
|
||||
/// test multiplication by one
|
||||
unittest {
|
||||
immutable block x0 = cast(immutable block) x"66e94bd4ef8a2c3b884cfa59ca342b2e";
|
||||
block x1 = x0;
|
||||
|
||||
block one;
|
||||
one[0] = ONE;
|
||||
|
||||
multiply(x1, one);
|
||||
|
||||
assert(x1 == x0, "GCM multiplication by ONE failed!");
|
||||
}
|
||||
|
||||
/// test multiplication
|
||||
unittest {
|
||||
|
||||
immutable block H = cast(immutable block)x"66e94bd4ef8a2c3b884cfa59ca342b2e";
|
||||
|
||||
block x1 = cast(immutable block) x"0388dace60b6a392f328c2b971b2fe78";
|
||||
|
||||
multiply(x1, H);
|
||||
|
||||
assert(x1 == x"5e2ec746917062882c85b0685353deb7", "GCM multiplication failed!");
|
||||
}
|
||||
|
||||
// http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf
|
||||
unittest {
|
||||
|
||||
immutable block H = cast(immutable block) x"73A23D80121DE2D5A850253FCF43120E";
|
||||
block X1 = cast(immutable block) x"D609B1F056637A0D46DF998D88E5222A";
|
||||
|
||||
multiply(X1, H);
|
||||
|
||||
assert(X1 == x"6B0BE68D67C6EE03EF7998E399C01CA4", "GCM multiplication failed!");
|
||||
}
|
||||
|
||||
// http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf
|
||||
unittest {
|
||||
|
||||
immutable block H = cast(immutable block) x"286D73994EA0BA3CFD1F52BF06A8ACF2";
|
||||
block X1 = cast(immutable block) x"D609B1F056637A0D46DF998D88E5222A";
|
||||
|
||||
multiply(X1, H);
|
||||
|
||||
assert(X1 == x"BA7C26F578254853CF321281A48317CA", "GCM multiplication failed!");
|
||||
}
|
||||
|
||||
// http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf
|
||||
unittest {
|
||||
|
||||
immutable block H = cast(immutable block) x"E4E01725D724C1215C7309AD34539257";
|
||||
block X1 = cast(immutable block) x"E20106D7CD0DF0761E8DCD3D88E54000";
|
||||
|
||||
multiply(X1, H);
|
||||
|
||||
assert(X1 == x"8DAD4981E33493018BB8482F69E4478C", "GCM multiplication failed!");
|
||||
}
|
||||
|
||||
/**
|
||||
* multiplication by P (only bit 1 = 1)
|
||||
*/
|
||||
static void multiplyP(T[] x) nothrow @nogc
|
||||
in {
|
||||
assert(x.length == 16, "x: invalid length. must be 16.");
|
||||
}
|
||||
body {
|
||||
T lsb = x[$-1] & 0x01;
|
||||
shiftRight(x);
|
||||
x[0] ^= R * lsb;
|
||||
}
|
||||
|
||||
// test multiplyP()
|
||||
unittest {
|
||||
|
||||
block X = cast(immutable block) x"E20106D7CD0DF0761E8DCD3D88E54000";
|
||||
immutable block P = cast(immutable block) x"40000000000000000000000000000000";
|
||||
|
||||
block XmultP;
|
||||
XmultP = X;
|
||||
|
||||
multiplyP(XmultP);
|
||||
|
||||
multiply(X, P);
|
||||
|
||||
assert(X == XmultP, "multiplyP() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* multiplication by P^8
|
||||
*/
|
||||
static void multiplyP8(T)(T[] x)
|
||||
{
|
||||
T lsw = x[$-1];
|
||||
shiftRight8(x);
|
||||
for (int i = 7; i >= 0; --i)
|
||||
{
|
||||
// if (lsw & (1 << i))
|
||||
// {
|
||||
// x[0] ^= ((R<<(T.sizeof*8-8)) >> (7 - i));
|
||||
// }
|
||||
// avoid branching:
|
||||
x[0] ^= (((R<<(T.sizeof*8-8)) >> (7 - i))) * (lsw & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
// test multiplyP8()
|
||||
unittest {
|
||||
|
||||
block X = cast(immutable block) x"E20106D7CD0DF0761E8DCD3D88E54000";
|
||||
immutable block P = cast(immutable block) x"40000000000000000000000000000000";
|
||||
|
||||
block XmultP8;
|
||||
XmultP8 = X;
|
||||
|
||||
multiplyP8(XmultP8);
|
||||
|
||||
foreach(i;0..8){
|
||||
multiply(X, P);
|
||||
}
|
||||
|
||||
assert(X == XmultP8, "multiplyP8() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift big endian number a 1 bit to the right.
|
||||
*/
|
||||
static void shiftRight(T)(T[] a) nothrow @nogc
|
||||
if(isIntegral!T)
|
||||
{
|
||||
T carryBit = 0;
|
||||
for(size_t i = 0; i < a.length; ++i) {
|
||||
T b = a[i];
|
||||
a[i] >>= 1;
|
||||
a[i] |= carryBit;
|
||||
carryBit = cast(T)(b << (T.sizeof * 8 - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// test right shift with bytes
|
||||
unittest {
|
||||
ubyte[] a = [0xf1,0x83,0x01];
|
||||
shiftRight(a);
|
||||
assert(a == [0x78,0xc1,0x80], "right shift failed");
|
||||
}
|
||||
|
||||
// test shiftRight
|
||||
unittest {
|
||||
|
||||
ubyte[16] a = cast(immutable ubyte[16]) x"59ed3f2bb1a0aaa07c9f56c6a504647b";
|
||||
foreach(i;0..8) {
|
||||
shiftRight(a);
|
||||
}
|
||||
|
||||
assert(a == x"0059ed3f2bb1a0aaa07c9f56c6a50464", "right shift failed");
|
||||
}
|
||||
|
||||
// with ints
|
||||
unittest {
|
||||
uint[] a = [0xfedcba98,0x76543210];
|
||||
foreach(i;0..8) {
|
||||
shiftRight(a);
|
||||
}
|
||||
assert(a == [0x00fedcba,0x98765432], "right shift failed");
|
||||
}
|
||||
|
||||
// with longs
|
||||
unittest {
|
||||
ulong[] a = [0x59ed3f2bb1a0aaa0,0x7c9f56c6a504647b];
|
||||
foreach(i;0..8) {
|
||||
shiftRight(a);
|
||||
}
|
||||
assert(a == [0x0059ed3f2bb1a0aa,0xa07c9f56c6a50464], "right shift failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift big endian number a 8 bits to the right.
|
||||
*/
|
||||
static void shiftRight8(T)(T[] a) nothrow @nogc {
|
||||
T carryBit = 0;
|
||||
for(size_t i = 0; i < a.length; ++i) {
|
||||
T b = a[i];
|
||||
a[i] >>= 8;
|
||||
a[i] |= carryBit;
|
||||
carryBit = cast(T)(b << (T.sizeof * 8 - 8));
|
||||
}
|
||||
}
|
||||
|
||||
// static void shiftRight(T)(T[] a, ubyte n) nothrow @nogc {
|
||||
// T carryBit = 0;
|
||||
// for(size_t i = 0; i < a.length; ++i) {
|
||||
// T b = a[i];
|
||||
// a[i] >>= n;
|
||||
// a[i] |= carryBit;
|
||||
// carryBit = cast(T)(b << (T.sizeof * 8 - n));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// static void shiftRight(ubyte[] a, ubyte n) nothrow @nogc {
|
||||
// shiftRight(cast(uint[])a, n);
|
||||
// }
|
||||
|
||||
// test shiftRight8()
|
||||
unittest {
|
||||
ubyte[16] a = cast(immutable ubyte[16])x"59ed3f2bb1a0aaa07c9f56c6a504647b";
|
||||
ubyte[16] b = a;
|
||||
foreach(i;0..8) {
|
||||
shiftRight(a);
|
||||
}
|
||||
|
||||
shiftRight8(b);
|
||||
|
||||
assert(a == b, "right shift by 8 bits failed");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user