View source code Display the source code in std/digest/digest.d from which this page was generated on github. Improve this page Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone. Page wiki View or edit the community-maintained wiki page associated with this page.

Module std.digest.digest

This module describes the digest APIs used in Phobos. All digests follow these APIs. Additionally, this module contains useful helper methods which can be used with every digest type.

Category Functions
Template API isDigest DigestType hasPeek hasBlockSize ExampleDigest digest hexDigest makeDigest
OOP API Digest
Helper functions toHexString
Implementation helpers digestLength WrapperDigest

APIs

There are two APIs for digests: The template API and the OOP API. The template API uses structs and template helpers like isDigest. The OOP API implements digests as classes inheriting the Digest interface. All digests are named so that the template API struct is called "x" and the OOP API class is called "xDigest". For example we have MD5 <--> MD5Digest, CRC32 <--> CRC32Digest, etc.

The template API is slightly more efficient. It does not have to allocate memory dynamically, all memory is allocated on the stack. The OOP API has to allocate in the finish method if no buffer was provided. If you provide a buffer to the OOP APIs finish function, it doesn't allocate, but the Digest classes still have to be created using new which allocates them using the GC.

The OOP API is useful to change the digest function and/or digest backend at 'runtime'. The benefit here is that switching e.g. Phobos MD5Digest and an OpenSSLMD5Digest implementation is ABI compatible.

If just one specific digest type and backend is needed, the template API is usually a good fit. In this simplest case, the template API can even be used without templates: Just use the "x" structs directly.

CTFE

Digests do not work in CTFE

TODO

Digesting single bits (as opposed to bytes) is not implemented. This will be done as another template constraint helper (hasBitDigesting!T) and an additional interface (BitDigest)

Example

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");

Example

//Generating the hashes of a file, idiomatic D way
import std.digest.crc, std.digest.sha, std.digest.md;
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);
    }
}

Example

//Generating the hashes of a file using the template API
import std.digest.crc, std.digest.sha, std.digest.md;
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);
    }
}

Example

import std.digest.crc, std.digest.sha, std.digest.md;
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);
    }
}

Functions

Name Description
digest This is a convenience function to calculate a hash using the template API. Every digest passing the isDigest test can be used with this function.
digest This overload of the digest function handles arrays.
hexDigest This is a convenience function similar to digest, but it returns the string representation of the hash. Every digest passing the isDigest test can be used with this function.
hexDigest This overload of the hexDigest function handles arrays.
makeDigest This is a convenience function which returns an initialized digest, so it's not necessary to call start manually.
toHexString Used to convert a hash value (a static or dynamic array of ubytes) to a string. Can be used with the OOP and with the template API.

Interfaces

Name Description
Digest This describes the OOP API. To understand when to use the template API and when to use the OOP API, see the module documentation at the top of this page.

Classes

Name Description
WrapperDigest Wraps a template API hash struct into a Digest interface. Modules providing digest implementations will usually provide an alias for this template (e.g. MD5Digest, SHA1Digest, ...).

Structs

Name Description
ExampleDigest This documents the general structure of a Digest in the template API. All digest implementations should implement the following members and therefore pass the isDigest test.

Enums

Name Description
Order See toHexString

Templates

Name Description
DigestType Use this template to get the type which is returned by a digest's finish method.

Enum values

Name Type Description
digestLength This helper is used internally in the WrapperDigest template, but it might be useful for other purposes as well. It returns the length (in bytes) of the hash value produced by T.
hasBlockSize Checks whether the digest has a blockSize member, which contains the digest's internal block size in bits. It is primarily used by std.digest.hmac.HMAC.
hasPeek Used to check if a digest supports the peek method. Peek has exactly the same function signatures as finish, but it doesn't reset the digest's internal state.
isDigest Use this to check if a type is a digest. See ExampleDigest to see what a type must provide to pass this check.

Authors

Johannes Pfau

License

Boost License 1.0.

Comments