#include #include #include typedef enum { ENC = 1, DEC = -1 } encrypt_dir_t; static void encrypt(uint64_t block[4], const uint8_t *key, size_t keylen, encrypt_dir_t dir) { size_t half = 0; uint8_t round = 0, target = 6; /* 7 rounds, 256-bit security */ if (keylen <= 16) { if (keylen) target = 3; /* 4 rounds, 128-bit security */ else return; /* no key => no encryption */ } if (dir == DEC) { round = target; if (round & 1) half ^= 2; target = 0; } do { uint64_t f[4]; SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, &block[half], 16); SHA256_Update(&ctx, &round, 1); SHA256_Update(&ctx, key, keylen); SHA256_Final((unsigned char *)f, &ctx); half ^= 2; block[half] ^= f[0]; block[half + 1] ^= f[1]; if (round == target) break; round += dir; } while (1); } static void print(uint64_t block[4]) { printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", block[0], block[1], block[2], block[3]); } static const uint8_t key1[3] = {'k', 'e', 'y'}; static const uint8_t key2[32] = {'k', 'e', 'y'}; int main(void) { uint64_t block[4] = {1001, 2002, 3003, 4004}; encrypt(block, NULL, 0, ENC); print(block); encrypt(block, NULL, 0, DEC); print(block); encrypt(block, key1, sizeof(key1), ENC); print(block); encrypt(block, key1, sizeof(key1), DEC); print(block); encrypt(block, key2, sizeof(key2), ENC); print(block); encrypt(block, key2, sizeof(key2), DEC); print(block); return 0; }