Skip to content

Hashing and HMAC#

AHash provides message digests and HMAC. All functions return the raw digest as an AByteBuffer; use toHexString() or toBase64String() to get text.

Function Digest size
AHash::md5 16 bytes
AHash::sha1 20 bytes
AHash::sha256 32 bytes
AHash::sha512 64 bytes
AHash::sha256hmac 32 bytes

Warning

MD5 and SHA-1 are broken for security purposes. Use them only to interoperate with existing formats.

Hashing a buffer#

#include <AUI/Crypt/AHash.h>

AByteBuffer digest = AHash::sha256(AByteBuffer::fromString("hello"));
ALogger::info("Sample") << digest.toHexString();

Hashing a file or other stream#

Every digest has an overload accepting an input stream. The stream is read until its end, so there is no need to load the whole file in memory:

auto checksum = AHash::sha256(AFileInputStream("big.iso")).toHexString();

The overload takes aui::no_escape<IInputStream>, so it accepts a stream object (temporary or lvalue), a pointer or a shared pointer (for example _new<AByteBufferInputStream>(buffer)).

Verifying a download#

Compare the hex digest with the published one. Hex output is lowercase.

bool matches = AHash::sha256(AFileInputStream(path)).toHexString() == expectedSha256;

HMAC#

AHash::sha256hmac(in, key) computes HMAC-SHA256 of in with a secret key. It is used to authenticate a message with a shared secret (webhook signatures, signed cookies, etc...):

auto signature = AHash::sha256hmac(AByteBuffer::fromString(body), AByteBuffer::fromString(secret));
if (signature.toHexString() != receivedSignature) {
    throw AException("bad signature");
}

Note

The == comparison above is not constant-time. Whether that matters depends on your threat model.

Passwords#

A plain digest, even salted, is a poor way to store passwords: this module does not implement a password hashing function (bcrypt, scrypt, PBKDF2, argon2).

See also crypt for the module overview.