Upload files to "/"
This commit is contained in:
109
utils.d
Normal file
109
utils.d
Normal file
@@ -0,0 +1,109 @@
|
||||
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[]));
|
||||
}
|
||||
Reference in New Issue
Block a user