109 lines
2.3 KiB
D
109 lines
2.3 KiB
D
module angel.utils.cryptography.utils;
|
|
|
|
import core.vararg;
|
|
import std.traits;
|
|
import std.algorithm;
|
|
|
|
/// TODO: neat variadic implementation of `wipe()`
|
|
|
|
/// Clears data in memory.
|
|
@safe @nogc nothrow
|
|
void wipe(T)(ref T t) {
|
|
static if(is(typeof(cast (ubyte[]) t))) {
|
|
ubyte[] bytes = cast(ubyte[]) t;
|
|
|
|
bytes[] = 0;
|
|
|
|
if(!all!"a == 0"(bytes[])) {
|
|
// This should not get optimized away.
|
|
assert(false, "Wiping failed.");
|
|
}
|
|
} else static if ( is(typeof( {T a = T.init;} ))) {
|
|
t = T.init;
|
|
|
|
if(t != T.init) {
|
|
// This should not get optimized away.
|
|
assert(false, "Wiping failed.");
|
|
}
|
|
} else {
|
|
static assert(false, "Type not supported for wiping: " ~ T.stringof);
|
|
}
|
|
}
|
|
|
|
|
|
@safe @nogc nothrow
|
|
void wipe(T...)(ref T ts) {
|
|
foreach(ref t; ts) {
|
|
wipe(t);
|
|
}
|
|
}
|
|
|
|
// test static arrays
|
|
unittest {
|
|
ubyte[4] buf1 = [1,2,3,4];
|
|
uint[4] buf2 = [1,2,3,4];
|
|
size_t[4] buf3 = [1,2,3,4];
|
|
|
|
wipe(buf1);
|
|
wipe(buf2);
|
|
wipe(buf3);
|
|
|
|
assert(all!"a == 0"(buf1[]), "Failed to wipe ubyte[].");
|
|
assert(all!"a == 0"(buf2[]), "Failed to wipe ubyte[].");
|
|
assert(all!"a == 0"(buf3[]), "Failed to wipe ubyte[].");
|
|
}
|
|
|
|
// test dynamic arrays
|
|
unittest {
|
|
ubyte[] buf1 = [1,2,3,4];
|
|
uint[] buf2 = [1,2,3,4];
|
|
size_t[] buf3 = [1,2,3,4];
|
|
|
|
wipe(buf1, buf2, buf3);
|
|
|
|
assert(all!"a == 0"(buf1), "Failed to wipe ubyte[].");
|
|
assert(all!"a == 0"(buf2), "Failed to wipe ubyte[].");
|
|
assert(all!"a == 0"(buf3), "Failed to wipe ubyte[].");
|
|
}
|
|
|
|
unittest {
|
|
int a = 42;
|
|
int b = 84;
|
|
ubyte c = 1;
|
|
|
|
wipe(a, b, c);
|
|
|
|
assert(a == 0 && b == 0 && c == 0, "Wiping integer failed!");
|
|
}
|
|
|
|
/// Compares a and b in constant time.
|
|
///
|
|
/// Returns: 0 if a == b, some other value if a != b.
|
|
bool crypto_equals(T)(in T[] a, in T[] b) pure nothrow @safe @nogc
|
|
in {
|
|
assert(a.length == b.length, "Unequal length.");
|
|
} body {
|
|
T result = 0;
|
|
size_t i = 0;
|
|
|
|
while(i < a.length) {
|
|
result |= a[i] ^ b[i];
|
|
++i;
|
|
}
|
|
|
|
if(i != a.length) {
|
|
// Just to be sure that the compiler optimization does not destroy const time.
|
|
assert(false);
|
|
}
|
|
|
|
return result == 0;
|
|
}
|
|
|
|
// test crypto_equals
|
|
unittest {
|
|
ubyte[32] f = 0;
|
|
immutable ubyte[32] zero = 0;
|
|
assert(crypto_equals(f[], zero[]));
|
|
f[8] = 1;
|
|
assert(!crypto_equals(f[], zero[]));
|
|
} |