Криптография

libapg содержит собственные реализации SHA-256, MD5 и CRC32, а также обёртки для удобного хеширования файлов.

SHA-256

Заголовок: apg/sha256.h. Реализация соответствует FIPS 180-4. Выходной дайджест — 32 байта (256 бит).

Потоковый API

void sha256_init(sha256_ctx *ctx);
void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len);
void sha256_final(sha256_ctx *ctx, uint8_t digest[32]);

Используется когда данные поступают частями:

sha256_ctx ctx;
sha256_init(&ctx);

uint8_t buf[4096];
size_t n;
while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
    sha256_update(&ctx, buf, n);

uint8_t digest[32];
sha256_final(&ctx, digest);

Хеширование файла

bool compute_sha256(const char *path, uint8_t digest[32]);

Удобная обёртка — открывает файл, читает целиком, закрывает. Возвращает false при ошибке чтения.

uint8_t digest[32];
if (!compute_sha256("/var/cache/apg/curl.apg", digest)) return false;

Перевод в hex

void sha256_hex(const uint8_t digest[32], char *hex);

Записывает hex-представление дайджеста в буфер hex. Буфер должен быть не менее 65 байт (64 символа + \0).

uint8_t digest[32];
char hex[65];

compute_sha256("curl.apg", digest);
sha256_hex(digest, hex);
printf("SHA256: %s\n", hex);

MD5

Заголовок: apg/md5.h. Поддерживается для обратной совместимости с пакетами APGv1. Выходной дайджест — 16 байт (128 бит).

void md5_init(md5_ctx *ctx);
void md5_update(md5_ctx *ctx, const uint8_t *data, size_t len);
void md5_final(uint8_t digest[16], md5_ctx *ctx);
bool compute_md5(const char *path, uint8_t digest[16]);

Порядок аргументов md5_final отличается от SHA-256: первый — digest, второй — ctx.

uint8_t digest[16];
compute_md5("package.apg", digest);

for (int i = 0; i < 16; i++)
    printf("%02x", digest[i]);
printf("\n");

CRC32

Заголовок: apg/crc32.h. Быстрый 32-битный алгоритм с предвычисленной таблицей.

unsigned int crc32(const unsigned char *buffer, unsigned int len);
unsigned int crc32_simple(const unsigned char *message, unsigned int len);
  • crc32 — оптимизированная версия с развёрткой цикла (DO8)
  • crc32_simple — простая реализация без оптимизаций
#include <apg/crc32.h>

uint8_t data[] = {0x01, 0x02, 0x03};
unsigned int crc = crc32(data, sizeof(data));
printf("CRC32: %08x\n", crc);

Сравнение алгоритмов

АлгоритмРазмерСкоростьПрименение
SHA-256256 битсредняяосновной (APGv2)
CRC3232 битабыстраяальтернативный
MD5128 битсредняяlegacy (APGv1)