Authentication provides secure cryptographic authentication primitives, including HMAC-SHA256, PBKDF2-HMAC-SHA256 for password-based key derivation, and Poly1305 MAC for message authentication. The library also supports ChaCha20-Poly1305 AEAD encryption and constant-time memory comparison for security-critical applications. Both C and C++ interfaces are provided for convenient one-shot and streaming usage.
Code reference for C and C++ APIs for the respective Fossil Logic library.
HEADER REFERENCE #
#ifndef FOSSIL_CRYPTIC_AUTH_H
#define FOSSIL_CRYPTIC_AUTH_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* =======================
* HMAC-SHA256
* ======================= */
/**
* @brief Computes HMAC-SHA256 for given data.
*
* @param key Pointer to the key.
* @param key_len Length of the key in bytes.
* @param data Pointer to the message data.
* @param data_len Length of the message in bytes.
* @param out 32-byte buffer for the resulting MAC.
*/
void fossil_cryptic_auth_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len, uint8_t out[32]);
/* =======================
* PBKDF2-HMAC-SHA256
* ======================= */
/**
* @brief PBKDF2-HMAC-SHA256 password-based key derivation.
*
* @param password Pointer to the password bytes.
* @param pass_len Length of the password.
* @param salt Pointer to the salt bytes.
* @param salt_len Length of the salt.
* @param iterations Number of iterations (recommended >= 100000).
* @param out Output buffer for derived key.
* @param out_len Length of the derived key.
*/
void fossil_cryptic_auth_pbkdf2_sha256(const uint8_t *password, size_t pass_len, const uint8_t *salt, size_t salt_len, uint32_t iterations, uint8_t *out, size_t out_len);
/* =======================
* Poly1305 (one-shot)
* ======================= */
/**
* @brief Compute Poly1305 tag for a message using a 32-byte key.
*
* Key format: 32 bytes, lower 16 bytes are r (clamped), upper 16 bytes are s.
* Output tag is 16 bytes.
*
* @param key 32-byte Poly1305 key
* @param msg Message bytes
* @param msg_len Message length
* @param tag 16-byte output tag
*/
void fossil_cryptic_auth_poly1305_auth(const uint8_t key[32], const uint8_t *msg, size_t msg_len, uint8_t tag[16]);
/* =======================
* Poly1305 streaming API
* ======================= */
/**
* @brief Opaque Poly1305 streaming context (small POD).
*
* You may reinitialize or reuse by calling fossil_cryptic_auth_poly1305_init().
*/
typedef struct {
uint32_t r[5]; /* r as 5 26-bit limbs (clamped) */
uint32_t h[5]; /* accumulator as 5 26-bit limbs */
uint32_t pad[4]; /* s (128-bit) as four 32-bit words little-endian */
size_t leftover; /* bytes in buffer */
uint8_t buffer[16]; /* partial block buffer */
} fossil_cryptic_auth_poly1305_ctx_t;
/**
* @brief Initialize Poly1305 streaming context with 32-byte key.
*
* @param ctx Pointer to context
* @param key 32-byte key
*/
void fossil_cryptic_auth_poly1305_init(fossil_cryptic_auth_poly1305_ctx_t *ctx, const uint8_t key[32]);
/**
* @brief Update Poly1305 context with message bytes.
*
* Can be called multiple times. Message is processed in 16-byte blocks internally.
*
* @param ctx Pointer to context
* @param msg Message bytes
* @param msg_len Length of message bytes
*/
void fossil_cryptic_auth_poly1305_update(fossil_cryptic_auth_poly1305_ctx_t *ctx, const uint8_t *msg, size_t msg_len);
/**
* @brief Finalize Poly1305 and produce 16-byte tag.
*
* After finalize, ctx may be reused by calling init() again.
*
* @param ctx Pointer to context
* @param tag 16-byte output tag
*/
void fossil_cryptic_auth_poly1305_finish(fossil_cryptic_auth_poly1305_ctx_t *ctx, uint8_t tag[16]);
/* =======================
* Utilities
* ======================= */
/**
* @brief Constant-time memory comparison.
*
* Returns 1 if equal, 0 otherwise. Runs in time dependent only on length.
*
* @param a pointer to first buffer
* @param b pointer to second buffer
* @param len length in bytes
* @return 1 if equal, 0 if different
*/
int fossil_cryptic_auth_consttime_equal(const uint8_t *a, const uint8_t *b, size_t len);
/* ----------------------------
* ChaCha20 core / stream XOR
* ---------------------------- */
/**
* @brief Compute a single 64-byte ChaCha20 block.
*
* @param key 32-byte key
* @param nonce 12-byte nonce
* @param counter 32-bit block counter (usually 0 for key block, 1..n for stream)
* @param out 64-byte output block
*/
void fossil_cryptic_auth_chacha20_block(const uint8_t key[32], const uint8_t nonce[12], uint32_t counter, uint8_t out[64]);
/**
* @brief XOR input with ChaCha20 keystream (encrypt/decrypt).
*
* Produces out[i] = in[i] ^ keystream[i], using the given counter as the
* initial 32-bit block counter (keystream block 0 corresponds to counter).
*
* @param key 32-byte key
* @param nonce 12-byte nonce
* @param counter initial 32-bit block counter (use 1 for AEAD encryption per RFC)
* @param in input bytes
* @param out output buffer (may alias in)
* @param len number of bytes to process
*/
void fossil_cryptic_auth_chacha20_xor(const uint8_t key[32], const uint8_t nonce[12], uint32_t counter, const uint8_t *in, uint8_t *out, size_t len);
/* ----------------------------
* ChaCha20-Poly1305 AEAD
* ---------------------------- */
/**
* @brief Encrypt plaintext with ChaCha20-Poly1305 (IETF), producing ciphertext and 16-byte tag.
*
* @param key 32-byte key
* @param nonce 12-byte nonce
* @param aad Additional authenticated data (may be NULL if aad_len == 0)
* @param aad_len Length of AAD
* @param plaintext Plaintext bytes
* @param pt_len Length of plaintext
* @param ciphertext Output buffer for ciphertext (must be at least pt_len). Can alias plaintext.
* @param tag 16-byte output tag
*/
void fossil_cryptic_auth_chacha20_poly1305_encrypt(const uint8_t key[32], const uint8_t nonce[12], const uint8_t *aad, size_t aad_len, const uint8_t *plaintext, size_t pt_len, uint8_t *ciphertext, uint8_t tag[16]);
/**
* @brief Decrypt ciphertext with ChaCha20-Poly1305 (IETF) and verify tag.
*
* @param key 32-byte key
* @param nonce 12-byte nonce
* @param aad AAD bytes (may be NULL if aad_len == 0)
* @param aad_len Length of AAD
* @param ciphertext Ciphertext bytes
* @param ct_len Length of ciphertext
* @param plaintext Output buffer for plaintext (must be at least ct_len). May alias ciphertext.
* @param tag 16-byte tag to verify
* @return 1 on success (tag OK), 0 on failure (tag mismatch)
*/
int fossil_cryptic_auth_chacha20_poly1305_decrypt(const uint8_t key[32], const uint8_t nonce[12], const uint8_t *aad, size_t aad_len, const uint8_t *ciphertext, size_t ct_len, uint8_t *plaintext, const uint8_t tag[16]);
#ifdef __cplusplus
}
#include <string>
#include <vector>
#include <array>
#include <cstdint>
#include <cstring>
namespace fossil {
namespace cryptic {
class Auth {
public:
/**
* @brief Computes HMAC-SHA256 for given data.
*
* @param key Pointer to the key.
* @param key_len Length of the key in bytes.
* @param data Pointer to the message data.
* @param data_len Length of the message in bytes.
* @param out 32-byte buffer for the resulting MAC.
*/
static std::array<uint8_t, 32> hmac_sha256(const uint8_t* key, size_t key_len, const uint8_t* data, size_t data_len) {
std::array<uint8_t, 32> out;
fossil_cryptic_auth_hmac_sha256(key, key_len, data, data_len, out.data());
return out;
}
/**
* @brief Computes PBKDF2-HMAC-SHA256.
*
* @param password Pointer to the password.
* @param pass_len Length of the password in bytes.
* @param salt Pointer to the salt.
* @param salt_len Length of the salt in bytes.
* @param iterations Number of iterations.
* @param out_len Length of the output key in bytes.
* @return Derived key.
*/
static std::vector<uint8_t> pbkdf2_sha256(const uint8_t* password, size_t pass_len, const uint8_t* salt, size_t salt_len, uint32_t iterations, size_t out_len) {
std::vector<uint8_t> out(out_len);
fossil_cryptic_auth_pbkdf2_sha256(password, pass_len, salt, salt_len, iterations, out.data(), out_len);
return out;
}
/**
* @brief Computes Poly1305 MAC for given message.
*
* @param key Pointer to the key.
* @param msg Pointer to the message data.
* @param msg_len Length of the message in bytes.
* @return 16-byte Poly1305 tag.
*/
static std::array<uint8_t, 16> poly1305_auth(const uint8_t key[32], const uint8_t* msg, size_t msg_len) {
std::array<uint8_t, 16> tag;
fossil_cryptic_auth_poly1305_auth(key, msg, msg_len, tag.data());
return tag;
}
};
} // namespace cryptic
} // namespace fossil
#endif
#endif /* FOSSIL_CRYPTIC_HASH_H */SAMPLE CODE C #
#include <fossil/cryptic/auth.h>
#include <stdio.h>
#include <string.h>
int main() {
uint8_t key[32] = {0};
const char* message = "Authenticate me!";
uint8_t tag[32];
// Compute HMAC-SHA256
fossil_cryptic_auth_hmac_sha256(key, sizeof(key), (const uint8_t*)message, strlen(message), tag);
// Print first 8 bytes of MAC in hex
for(int i = 0; i < 8; i++) printf("%02x", tag[i]);
printf("\n");
return 0;
}
SAMPLE CODE C++ #
#include <fossil/cryptic/auth.h>
#include <iostream>
#include <array>
#include <string>
int main() {
using namespace fossil::cryptic;
std::array<uint8_t, 32> key{}; // all zero key
std::string msg = "Authenticate me!";
// Compute HMAC-SHA256 using C++ wrapper
auto tag = Auth::hmac_sha256(key.data(), key.size(), reinterpret_cast<const uint8_t*>(msg.data()), msg.size());
// Print first 8 bytes in hex
for(size_t i = 0; i < 8; ++i) std::cout << std::hex << (int)tag[i];
std::cout << std::endl;
return 0;
}