# `crypto`

This library provides transport-neutral cryptographic predicates. It currently exports the `crypto` object with the predicates:

- `random_below/2`

- `random_bytes/2`

- `hex_bytes/2`

- `token_hex/2`

- `token_urlsafe/2`

- `secure_compare/2`

- `hkdf/5`

- `pbkdf2/6`

- `apr1/3`

- `password_hash/4`

- `password_hash_needs_rehash/3`

- `verify_password_hash/2`

The `random_below/2` predicate returns a uniformly distributed random integer greater than or equal to zero and less than the given exclusive upper bound.

The `random_bytes/2` predicate returns a list with the requested number of random bytes. It tries to read bytes from `/dev/urandom` first and falls back to a pseudo-random generator when that source is unavailable.

The `hex_bytes/2` predicate relates hexadecimal atoms with lists of bytes.

The `token_hex/2` and `token_urlsafe/2` predicates return either a lowercase hexadecimal token or a unpadded Base64URL token generated from the requested number of random bytes.

The `secure_compare/2` predicate provides constant-time comparison for byte sequences represented either as byte lists or atoms.

The `hkdf/5` and `pbkdf2/6` predicates provide portable key derivation implemented on top of the existing `hashes` and `hmac` libraries.

The `apr1/3` predicate computes Apache APR1 encoded checksums for password and salt byte sequences using a portable MD5-based implementation.

The `password_hash/4` predicate builds on top of `pbkdf2/6` to generate structured password-hash terms. The `password_hash_needs_rehash/3` predicate checks stored password-hash terms against the current PBKDF2 policy. The `verify_password_hash/2` predicate verifies `pbkdf2(Hash, Iterations, Salt, DerivedKey)`, `digest(Hash, StoredDigest)`, and `apr1(Salt, Checksum)` terms.

## API documentation

Open the ../../apis/library_index.html#crypto link in a web browser.

## Loading

To load the library, load the `loader.lgt` file:

    | ?- logtalk_load(crypto(loader)).

## Testing

To test this library, load the `tester.lgt` file:

    | ?- logtalk_load(crypto(tester)).

## Examples

Generate sixteen random bytes:

    | ?- crypto::random_bytes(16, Bytes).
    Bytes = [42,17,203,91,16,88,121,4,238,75,63,142,7,210,119,55]
    yes

Convert bytes to a hexadecimal atom:

    | ?- crypto::hex_bytes(Hex, [80,26,206]).
    Hex = '501ace'
    yes

Derive 32 bytes using HKDF-SHA-256:

    | ?- crypto::hkdf(sha256, [1,2,3,4], 32, Bytes, [salt([5,6,7,8]),info([9,10])]).
    Bytes = [...]
    yes

Compute an Apache APR1 checksum:

    | ?- crypto::apr1([112,97,115,115,119,111,114,100], [112,111,114,116,97,98,108,101], Checksum).
    Checksum = [107,117,110,70,78,90,57,114,48,81,57,54,51,88,98,115,116,101,79,79,87,46]
    yes