Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
247
Task/MD5-Implementation/D/md5-implementation.d
Normal file
247
Task/MD5-Implementation/D/md5-implementation.d
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
import std.bitmanip, core.stdc.string, std.conv, std.math, std.array,
|
||||
std.string;
|
||||
|
||||
version (D_InlineAsm_X86) {} else {
|
||||
static assert(false, "For X86 machine only.");
|
||||
}
|
||||
|
||||
// CTFE construction of transform expressions.
|
||||
uint S(in uint n) pure nothrow @safe @nogc {
|
||||
static immutable aux = [7u, 12, 17, 22, 5, 9, 14, 20, 4, 11,
|
||||
16, 23, 6, 10, 15, 21];
|
||||
return aux[(n / 16) * 4 + (n % 4)];
|
||||
}
|
||||
|
||||
uint K(in uint n) pure nothrow @safe @nogc {
|
||||
uint r = 0;
|
||||
if (n <= 15)
|
||||
r = n;
|
||||
else if (n <= 31)
|
||||
r = 5 * n + 1;
|
||||
else if (n <= 47)
|
||||
r = 3 * n + 5;
|
||||
else
|
||||
r = 7 * n;
|
||||
return r % 16;
|
||||
}
|
||||
|
||||
uint T(in uint n) pure nothrow @nogc {
|
||||
return cast(uint)(abs(sin(n + 1.0L)) * (2UL ^^ 32));
|
||||
}
|
||||
|
||||
string[] ABCD(in int n) pure nothrow {
|
||||
enum abcd = ["EAX", "EBX", "ECX", "EDX"];
|
||||
return abcd[(64 - n) % 4 .. 4] ~ abcd[0 .. (64 - n) % 4];
|
||||
}
|
||||
|
||||
string SUB(in int n, in string s) pure nothrow {
|
||||
return s
|
||||
.replace("ax", n.ABCD[0])
|
||||
.replace("bx", n.ABCD[1])
|
||||
.replace("cx", n.ABCD[2])
|
||||
.replace("dx", n.ABCD[3]);
|
||||
}
|
||||
|
||||
// FF, GG, HH & II expressions part 1 (F, G, H, I).
|
||||
string fghi1(in int n) pure nothrow @nogc {
|
||||
switch (n / 16) {
|
||||
case 0:
|
||||
// (bb & cc) | (~bb & dd)
|
||||
return q{
|
||||
mov ESI, bx;
|
||||
mov EDI, bx;
|
||||
not ESI;
|
||||
and EDI, cx;
|
||||
and ESI, dx;
|
||||
or EDI, ESI;
|
||||
add ax, EDI;
|
||||
};
|
||||
case 1:
|
||||
// (dd & bb) | (~dd & cc)
|
||||
return q{
|
||||
mov ESI, dx;
|
||||
mov EDI, dx;
|
||||
not ESI;
|
||||
and EDI, bx;
|
||||
and ESI, cx;
|
||||
or EDI, ESI;
|
||||
add ax, EDI;
|
||||
};
|
||||
case 2: // (bb ^ cc ^ dd)
|
||||
return q{
|
||||
mov EDI, bx;
|
||||
xor EDI, cx;
|
||||
xor EDI, dx;
|
||||
add ax, EDI;
|
||||
};
|
||||
case 3: // (cc ^ (bb | ~dd))
|
||||
return q{
|
||||
mov EDI, dx;
|
||||
not EDI;
|
||||
or EDI, bx;
|
||||
xor EDI, cx;
|
||||
add ax, EDI;
|
||||
};
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// FF, GG, HH & II expressions part 2.
|
||||
string fghi2(in int n) pure nothrow {
|
||||
return q{
|
||||
add ax, [EBP + 4 * KK];
|
||||
add ax, TT;
|
||||
} ~ n.fghi1;
|
||||
}
|
||||
|
||||
// FF, GG, HH & II expressions prepended with previous parts
|
||||
// & subsitute ABCD.
|
||||
string FGHI(in int n) pure nothrow {
|
||||
// aa = ((aa << SS)|( aa >>> (32 - SS))) + bb = ROL(aa, SS) + bb
|
||||
return SUB(n, n.fghi2 ~ q{
|
||||
rol ax, SS;
|
||||
add ax, bx;
|
||||
});
|
||||
}
|
||||
|
||||
string genExpr(uint n) pure nothrow {
|
||||
return FGHI(n)
|
||||
.replace("SS", n.S.text)
|
||||
.replace("KK", n.K.text)
|
||||
.replace("TT", "0x" ~ to!string(n.T, 16));
|
||||
}
|
||||
|
||||
string genTransformCode(int n) pure nothrow {
|
||||
return (n < 63) ? n.genExpr ~ genTransformCode(n + 1) : n.genExpr;
|
||||
}
|
||||
|
||||
enum string coreZMD5 = 0.genTransformCode;
|
||||
|
||||
struct ZMD5 {
|
||||
uint[4] state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
|
||||
ulong count;
|
||||
ubyte[64] buffer;
|
||||
|
||||
ubyte[64] padding = [
|
||||
0x80, 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];
|
||||
|
||||
private void transform(ubyte* block) pure nothrow @nogc {
|
||||
uint[16] x = void;
|
||||
|
||||
version (BigEndian) {
|
||||
foreach (immutable i; 0 .. 16)
|
||||
x[i] = littleEndianToNative!uint(*cast(ubyte[4]*)&block[i * 4]);
|
||||
} else {
|
||||
(cast(ubyte*)x.ptr)[0 .. 64] = block[0 .. 64];
|
||||
}
|
||||
|
||||
auto pState = state.ptr;
|
||||
auto pBuffer = x.ptr;
|
||||
|
||||
asm pure nothrow @nogc {
|
||||
mov ESI, pState[EBP];
|
||||
mov EDX, [ESI + 3 * 4];
|
||||
mov ECX, [ESI + 2 * 4];
|
||||
mov EBX, [ESI + 1 * 4];
|
||||
mov EAX, [ESI + 0 * 4];
|
||||
push EBP;
|
||||
push ESI;
|
||||
|
||||
mov EBP, pBuffer[EBP];
|
||||
}
|
||||
|
||||
mixin("asm pure nothrow @nogc { " ~ coreZMD5 ~ "}");
|
||||
|
||||
asm pure nothrow @nogc {
|
||||
pop ESI;
|
||||
pop EBP;
|
||||
add [ESI + 0 * 4], EAX;
|
||||
add [ESI + 1 * 4], EBX;
|
||||
add [ESI + 2 * 4], ECX;
|
||||
add [ESI + 3 * 4], EDX;
|
||||
}
|
||||
x[] = 0;
|
||||
}
|
||||
|
||||
void update(in void[] input) pure nothrow @nogc {
|
||||
auto inputLen = input.length;
|
||||
uint index = (count >> 3) & 0b11_1111U;
|
||||
count += inputLen * 8;
|
||||
immutable uint partLen = 64 - index;
|
||||
|
||||
uint i;
|
||||
if (inputLen >= partLen) {
|
||||
memcpy(&buffer[index], input.ptr, partLen);
|
||||
transform(buffer.ptr);
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
transform((cast(ubyte[])input)[i .. i + 64].ptr);
|
||||
index = 0;
|
||||
} else
|
||||
i = 0;
|
||||
|
||||
if (inputLen - i)
|
||||
memcpy(&buffer[index], &input[i], inputLen - i);
|
||||
}
|
||||
|
||||
void finish(ref ubyte[16] digest) pure nothrow @nogc {
|
||||
ubyte[8] bits = void;
|
||||
bits[0 .. 8] = nativeToLittleEndian(count)[];
|
||||
|
||||
immutable uint index = (count >> 3) & 0b11_1111U;
|
||||
immutable uint padLen = (index < 56) ?
|
||||
(56 - index) : (120 - index);
|
||||
update(padding[0 .. padLen]);
|
||||
update(bits);
|
||||
|
||||
digest[0 .. 4] = nativeToLittleEndian(state[0])[];
|
||||
digest[4 .. 8] = nativeToLittleEndian(state[1])[];
|
||||
digest[8 .. 12] = nativeToLittleEndian(state[2])[];
|
||||
digest[12 .. 16] = nativeToLittleEndian(state[3])[];
|
||||
|
||||
// Zeroize sensitive information.
|
||||
memset(&this, 0, ZMD5.sizeof);
|
||||
}
|
||||
}
|
||||
|
||||
string getDigestString(in void[][] data...) pure {
|
||||
ZMD5 ctx;
|
||||
foreach (datum; data)
|
||||
ctx.update(datum);
|
||||
ubyte[16] digest;
|
||||
ctx.finish(digest);
|
||||
return format("%-(%02X%)", digest);
|
||||
}
|
||||
|
||||
|
||||
void main() { // Benchmark code --------------
|
||||
import std.stdio, std.datetime, std.digest.md;
|
||||
|
||||
writefln(`md5 digest("") = %-(%02X%)`, "".md5Of);
|
||||
writefln(`zmd5 digest("") = %s`, "".getDigestString);
|
||||
|
||||
enum megaBytes = 512;
|
||||
writefln("\nTest performance / message size %dMBytes:", megaBytes);
|
||||
auto data = new float[megaBytes * 0x40000 + 13];
|
||||
|
||||
StopWatch sw;
|
||||
sw.start;
|
||||
immutable d1 = data.md5Of;
|
||||
sw.stop;
|
||||
immutable time1 = sw.peek.msecs / 1000.0;
|
||||
writefln("digest(data) = %-(%02X%)", d1);
|
||||
writefln("std.md5: %8.2f M/sec ( %8.2f secs)",
|
||||
megaBytes / time1, time1);
|
||||
|
||||
sw.reset;
|
||||
sw.start;
|
||||
immutable d2 = data.getDigestString;
|
||||
sw.stop;
|
||||
immutable time2 = sw.peek.msecs / 1000.0;
|
||||
writefln("digest(data) = %s", d2);
|
||||
writefln("zmd5 : %8.2f M/sec ( %8.2f secs)",
|
||||
megaBytes / time2, time2);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue