Skip to content

Instantly share code, notes, and snippets.

@odzhan
Created June 1, 2022 09:41
Show Gist options
  • Save odzhan/9c8edcb76ad0a5e038bb7f5633f21651 to your computer and use it in GitHub Desktop.
Save odzhan/9c8edcb76ad0a5e038bb7f5633f21651 to your computer and use it in GitHub Desktop.
256-Bit Hash using Xoodoo permutation
//
// Charm 256-bit hash ripped from: https://github.com/jedisct1/charm
//
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define XOODOO_ROUNDS 12
#define ROTR32(x, b) (uint32_t)(((x) >> (b)) | ((x) << (32 - (b))))
#define SWAP32(s, u, v) \
do { \
t = (s)[u]; \
(s)[u] = (s)[v], (s)[v] = t; \
} while (0)
// round constants
uint32_t RK[12] = { 0x058, 0x038, 0x3c0, 0x0d0, 0x120, 0x014,
0x060, 0x02c, 0x380, 0x0f0, 0x1a0, 0x012 };
// Xoodoo permutation function
void
permute(uint32_t s[12]) {
uint32_t e[4], a, b, c, t, r, i;
for (r = 0; r < XOODOO_ROUNDS; r++) {
for (i = 0; i < 4; i++) {
e[i] = ROTR32(s[i] ^ s[i + 4] ^ s[i + 8], 18);
e[i] ^= ROTR32(e[i], 9);
}
for (i = 0; i < 12; i++) {
s[i] ^= e[(i - 1) & 3];
}
SWAP32(s, 7, 4);
SWAP32(s, 7, 5);
SWAP32(s, 7, 6);
s[0] ^= RK[r];
for (i = 0; i < 4; i++) {
a = s[i];
b = s[i + 4];
c = ROTR32(s[i + 8], 21);
s[i + 8] = ROTR32((b & ~a) ^ c, 24);
s[i + 4] = ROTR32((a & ~c) ^ b, 31);
s[i] ^= c & ~b;
}
SWAP32(s, 8, 10);
SWAP32(s, 9, 11);
}
}
void
squeeze(uint32_t s[12], uint8_t ds[16]) {
memcpy(ds, s, 16);
permute(s);
}
void
xor128(void *output, void *input) {
uint8_t *out = (uint8_t*) output;
uint8_t *in = (uint8_t*) input;
size_t i;
for (i = 0; i < 16; i++) {
out[i] ^= in[i];
}
}
void
charm_hash(
uint32_t s[12],
uint8_t h[32],
uint8_t *msg,
size_t len)
{
uint8_t padded[16 + 1];
size_t off = 0;
size_t leftover;
if (len > 16) {
for (; off < len - 16; off += 16) {
xor128(s, &msg[off]);
permute(s);
}
}
leftover = len - off;
memset(padded, 0, 16);
memcpy(padded, &msg[off], leftover);
padded[leftover] = 0x80;
xor128(s, padded);
s[11] ^= (1UL << 24 | (uint32_t) leftover >> 4 << 25);
permute(s);
squeeze(s, &h[0]);
squeeze(s, &h[16]);
}
#if defined(TEST)
int
main(int argc, char *argv[]) {
if (argc != 2) {
printf("charm_hash <string>\n");
return 0;
}
int i;
uint8_t hash[32];
uint32_t state[12]={0};
uint8_t *msg = (uint8_t*)argv[1];
size_t msglen = strlen(msg);
charm_hash(state, hash, msg, msglen);
printf("xoodoo-256(\"%s\")= ", msg);
for(i=0; i<32; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment