blob: 330326c3fdecba9e7783e828e327ed67e18b2e23 [file] [log] [blame]
@system unittest
{
import std.digest;
import std.digest.crc;
//Simple example
char[8] hexHash = hexDigest!CRC32("The quick brown fox jumps over the lazy dog");
assert(hexHash == "39A34F41");
//Simple example, using the API manually
CRC32 context = makeDigest!CRC32();
context.put(cast(ubyte[])"The quick brown fox jumps over the lazy dog");
ubyte[4] hash = context.finish();
assert(toHexString(hash) == "39A34F41");
}
@system unittest
{
import std.digest;
//Generating the hashes of a file, idiomatic D way
import std.digest.crc, std.digest.md, std.digest.sha;
import std.stdio;
// Digests a file and prints the result.
void digestFile(Hash)(string filename)
if (isDigest!Hash)
{
auto file = File(filename);
auto result = digest!Hash(file.byChunk(4096 * 1024));
writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result));
}
void main(string[] args)
{
foreach (name; args[1 .. $])
{
digestFile!MD5(name);
digestFile!SHA1(name);
digestFile!CRC32(name);
}
}
}
@system unittest
{
import std.digest;
//Generating the hashes of a file using the template API
import std.digest.crc, std.digest.md, std.digest.sha;
import std.stdio;
// Digests a file and prints the result.
void digestFile(Hash)(ref Hash hash, string filename)
if (isDigest!Hash)
{
File file = File(filename);
//As digests imlement OutputRange, we could use std.algorithm.copy
//Let's do it manually for now
foreach (buffer; file.byChunk(4096 * 1024))
hash.put(buffer);
auto result = hash.finish();
writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result));
}
void uMain(string[] args)
{
MD5 md5;
SHA1 sha1;
CRC32 crc32;
md5.start();
sha1.start();
crc32.start();
foreach (arg; args[1 .. $])
{
digestFile(md5, arg);
digestFile(sha1, arg);
digestFile(crc32, arg);
}
}
}
@system unittest
{
import std.digest;
import std.digest.crc, std.digest.md, std.digest.sha;
import std.stdio;
// Digests a file and prints the result.
void digestFile(Digest hash, string filename)
{
File file = File(filename);
//As digests implement OutputRange, we could use std.algorithm.copy
//Let's do it manually for now
foreach (buffer; file.byChunk(4096 * 1024))
hash.put(buffer);
ubyte[] result = hash.finish();
writefln("%s (%s) = %s", typeid(hash).toString(), filename, toHexString(result));
}
void umain(string[] args)
{
auto md5 = new MD5Digest();
auto sha1 = new SHA1Digest();
auto crc32 = new CRC32Digest();
foreach (arg; args[1 .. $])
{
digestFile(md5, arg);
digestFile(sha1, arg);
digestFile(crc32, arg);
}
}
}
@system unittest
{
import std.digest;
//Using the OutputRange feature
import std.algorithm.mutation : copy;
import std.digest.md;
import std.range : repeat;
auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
auto ctx = makeDigest!MD5();
copy(oneMillionRange, &ctx); //Note: You must pass a pointer to copy!
assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21");
}
@system unittest
{
import std.digest;
import std.digest.crc;
static assert(isDigest!CRC32);
}
@system unittest
{
import std.digest;
import std.digest.crc;
void myFunction(T)()
if (isDigest!T)
{
T dig;
dig.start();
auto result = dig.finish();
}
myFunction!CRC32();
}
@system unittest
{
import std.digest;
import std.digest.crc;
assert(is(DigestType!(CRC32) == ubyte[4]));
}
@system unittest
{
import std.digest;
import std.digest.crc;
CRC32 dig;
dig.start();
DigestType!CRC32 result = dig.finish();
}
@system unittest
{
import std.digest;
import std.digest.crc, std.digest.md;
assert(!hasPeek!(MD5));
assert(hasPeek!CRC32);
}
@system unittest
{
import std.digest;
import std.digest.crc;
void myFunction(T)()
if (hasPeek!T)
{
T dig;
dig.start();
auto result = dig.peek();
}
myFunction!CRC32();
}
@system unittest
{
import std.digest;
import std.digest.hmac, std.digest.md;
static assert(hasBlockSize!MD5 && MD5.blockSize == 512);
static assert(hasBlockSize!(HMAC!MD5) && HMAC!MD5.blockSize == 512);
}
@system unittest
{
import std.digest;
import std.digest.md;
import std.range : repeat;
auto testRange = repeat!ubyte(cast(ubyte)'a', 100);
auto md5 = digest!MD5(testRange);
}
@system unittest
{
import std.digest;
import std.digest.crc, std.digest.md, std.digest.sha;
auto md5 = digest!MD5( "The quick brown fox jumps over the lazy dog");
auto sha1 = digest!SHA1( "The quick brown fox jumps over the lazy dog");
auto crc32 = digest!CRC32("The quick brown fox jumps over the lazy dog");
assert(toHexString(crc32) == "39A34F41");
}
@system unittest
{
import std.digest;
import std.digest.crc;
auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
assert(toHexString(crc32) == "39A34F41");
}
@system unittest
{
import std.digest;
import std.digest.md;
import std.range : repeat;
auto testRange = repeat!ubyte(cast(ubyte)'a', 100);
assert(hexDigest!MD5(testRange) == "36A92CC94A9E0FA21F625F8BFB007ADF");
}
@system unittest
{
import std.digest;
import std.digest.crc;
assert(hexDigest!(CRC32, Order.decreasing)("The quick brown fox jumps over the lazy dog") == "414FA339");
}
@system unittest
{
import std.digest;
import std.digest.crc;
assert(hexDigest!(CRC32, Order.decreasing)("The quick ", "brown ", "fox jumps over the lazy dog") == "414FA339");
}
@system unittest
{
import std.digest;
import std.digest.md;
auto md5 = makeDigest!MD5();
md5.put(0);
assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71");
}
@system unittest
{
import std.digest;
//Using the OutputRange feature
import std.algorithm.mutation : copy;
import std.digest.md;
import std.range : repeat;
auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
auto ctx = new MD5Digest();
copy(oneMillionRange, ctx);
assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21");
}
@system unittest
{
import std.digest;
import std.digest.crc, std.digest.md, std.digest.sha;
ubyte[] md5 = (new MD5Digest()).digest("The quick brown fox jumps over the lazy dog");
ubyte[] sha1 = (new SHA1Digest()).digest("The quick brown fox jumps over the lazy dog");
ubyte[] crc32 = (new CRC32Digest()).digest("The quick brown fox jumps over the lazy dog");
assert(crcHexString(crc32) == "414FA339");
}
@system unittest
{
import std.digest;
import std.digest.crc;
ubyte[] crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog");
assert(crcHexString(crc32) == "414FA339");
}
@system unittest
{
import std.digest;
void test(Digest dig)
{
dig.put(cast(ubyte) 0); //single ubyte
dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
ubyte[10] buf;
dig.put(buf); //buffer
}
}
@safe unittest
{
import std.digest;
import std.digest.crc : CRC32;
auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
assert(crc32.toHexString!(Order.decreasing) == "414FA339");
assert(crc32.toHexString!(LetterCase.lower, Order.decreasing) == "414fa339");
}
@safe unittest
{
import std.digest;
import std.digest.crc;
//Test with template API:
auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
//Lower case variant:
assert(toHexString!(LetterCase.lower)(crc32) == "39a34f41");
//Usually CRCs are printed in this order, though:
assert(toHexString!(Order.decreasing)(crc32) == "414FA339");
assert(toHexString!(LetterCase.lower, Order.decreasing)(crc32) == "414fa339");
}
@safe unittest
{
import std.digest;
import std.digest.crc;
// With OOP API
auto crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog");
//Usually CRCs are printed in this order, though:
assert(toHexString!(Order.decreasing)(crc32) == "414FA339");
}
@system unittest
{
import std.digest;
import std.digest.md;
//Simple example
auto hash = new WrapperDigest!MD5();
hash.put(cast(ubyte) 0);
auto result = hash.finish();
}
@system unittest
{
import std.digest;
//using a supplied buffer
import std.digest.md;
ubyte[16] buf;
auto hash = new WrapperDigest!MD5();
hash.put(cast(ubyte) 0);
auto result = hash.finish(buf[]);
//The result is now in result (and in buf). If you pass a buffer which is bigger than
//necessary, result will have the correct length, but buf will still have it's original
//length
}
@system pure unittest
{
import std.digest;
import std.digest.hmac : hmac;
import std.digest.sha : SHA1;
import std.string : representation;
// a typical HMAC data integrity verification
auto secret = "A7GZIP6TAQA6OHM7KZ42KB9303CEY0MOV5DD6NTV".representation;
auto data = "data".representation;
auto hex1 = data.hmac!SHA1(secret).toHexString;
auto hex2 = data.hmac!SHA1(secret).toHexString;
auto hex3 = "data1".representation.hmac!SHA1(secret).toHexString;
assert( secureEqual(hex1[], hex2[]));
assert(!secureEqual(hex1[], hex3[]));
}
@safe unittest
{
import std.digest;
assert(isHexString("0x0123456789ABCDEFabcdef"));
assert(isHexString("0123456789ABCDEFabcdef"));
assert(!isHexString("g"));
assert(!isHexString("#"));
}
@safe unittest
{
import std.digest;
import std.range.primitives : ElementType, isForwardRange;
import std.traits : ReturnType;
// The decoder implements a forward range.
static assert(isForwardRange!(ReturnType!(fromHexStringAsRange!string)));
static assert(isForwardRange!(ReturnType!(fromHexStringAsRange!wstring)));
static assert(isForwardRange!(ReturnType!(fromHexStringAsRange!dstring)));
// The element type of the range is always `ubyte`.
static assert(
is(ElementType!(ReturnType!(fromHexStringAsRange!string)) == ubyte)
);
static assert(
is(ElementType!(ReturnType!(fromHexStringAsRange!wstring)) == ubyte)
);
static assert(
is(ElementType!(ReturnType!(fromHexStringAsRange!dstring)) == ubyte)
);
}
@safe unittest
{
import std.digest;
// Single byte
assert("0xff".fromHexString == [255]);
assert("0xff"w.fromHexString == [255]);
assert("0xff"d.fromHexString == [255]);
assert("0xC0".fromHexString == [192]);
assert("0x00".fromHexString == [0]);
// Nothing
assert("".fromHexString == []);
assert(""w.fromHexString == []);
assert(""d.fromHexString == []);
// Nothing but a prefix
assert("0x".fromHexString == []);
assert("0x"w.fromHexString == []);
assert("0x"d.fromHexString == []);
// Half a byte
assert("0x1".fromHexString == [0x01]);
assert("0x1"w.fromHexString == [0x01]);
assert("0x1"d.fromHexString == [0x01]);
// Mixed case is fine.
assert("0xAf".fromHexString == [0xAF]);
assert("0xaF".fromHexString == [0xAF]);
// Multiple bytes
assert("0xfff".fromHexString == [0x0F, 0xFF]);
assert("0x123AaAa".fromHexString == [0x01, 0x23, 0xAA, 0xAA]);
assert("EBBBBF".fromHexString == [0xEB, 0xBB, 0xBF]);
// md5 sum
assert("d41d8cd98f00b204e9800998ecf8427e".fromHexString == [
0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E,
]);
}
@safe unittest
{
import std.digest;
// Cycle self-test
const ubyte[] initial = [0x00, 0x12, 0x34, 0xEB];
assert(initial == initial.toHexString().fromHexString());
}