Skip to content

Instantly share code, notes, and snippets.

@thequux
Created April 2, 2015 18:20
Show Gist options
  • Save thequux/1c51a13141ac81fe27b2 to your computer and use it in GitHub Desktop.
Save thequux/1c51a13141ac81fe27b2 to your computer and use it in GitHub Desktop.
Spritz in C
// This file was written by TQ Hirsch <thequux@thequux.com>.
// It may be used under any of the following licenses, at your
// discretion:
// - Public Domain
// - WTFPLv2
// - CC-0
// - MIT
// - ISC
// This file may be used as a header for separate compilation by
// #define-ing SPRITZ_HEADER_ONLY. Alternatively, cut this file at the
// line that contains "=== END HEADER ==="; the top half is usuable as
// a header while the bottom half contains the implementation. If you
// do this, the header should be called "spritz.h"
#ifndef SPRITZ__H
#define SPRITZ__H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spritz_t {
uint8_t s[256];
uint8_t i,j,k,z,a,w;
} spritz_t;
#define SPRITZ_STATIC_INIT { \
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, \
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, \
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, \
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, \
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, \
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, \
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, \
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, \
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, \
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}, \
0, 0, 0, 0, 0, 1}
void spritz_init(spritz_t *sp);
void spritz_absorb(spritz_t *sp, const uint8_t *buf, size_t len);
void spritz_absorb_stop(spritz_t *sp);
void spritz_squeeze(spritz_t *sp, const uint8_t *buf, size_t len);
#ifdef __cplusplus
}
#endif
#endif // !SPRITZ__H
// === END HEADER ===
// === BEGIN CODE ===
#ifndef SPRITZ_HEADER_ONLY
#ifndef SPRITZ__H
#include "spritz.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define S (sp->s)
#define I (sp->i)
#define J (sp->j)
#define K (sp->k)
#define Z (sp->z)
#define A (sp->a)
#define W (sp->w)
#define SWAP(a,b) do { uint8_t t = (a); (a) = (b); (b) = t; } while(0)
#define SPRITZ_ABS_NIBBLE(b) do { \
if (A == 128) spritz_shuffle(sp); \
SWAP(S[A], S[128 + ((b) & 0xF)]); \
A++; \
}
#define SPRITZ_UPDATE() do { \
I += W; \
J = K + S[J + S[I]]; \
K = I + K + S[J]; \
SWAP(S[I], S[J]); \
} while (0)
void spritz_init(spritz_t *sp) {
int i;
for (i = 0; i < 256; i++) {
S[i] = (uint8_t)i;
}
I = J = K = Z = A = 0;
W = 1;
}
void spritz_absorb(spritz_t *sp, const uint8_t *buf, size_t len) {
int i;
uint8_t b, t;
for (i = 0; i < len; i++) {
b = buf[i];
SPRITZ_ABS_NIBBLE(b & 0xF);
SPRITZ_ABS_NIBBLE(b >> 4);
}
}
void spritz_absorb_stop(spritz_t *sp) {
if (A == 128) spritz_shuffle(sp);
A++;
}
void spritz_squeeze(spritz_t *sp, const uint8_t *buf, size_t len) {
if (A > 0) spritz_shuffle(sp);
int i;
for (i = 0; i < len; i++) {
SPRITZ_UPDATE();
buf[i] = Z = S[J + S[I + S[Z+K]]];
}
}
void spritz_whip(spritz_t *sp) {
int i;
for (i = 0; i < 512; i++) SPRITZ_UPDATE();
w += 2;
}
void spritz_crush(spritz_t *sp) {
int i;
for (i = 0; i < 128; i++) {
uint8_t a,b, m;
a = S[i];
b = S[255-i];
// take high bit of (b-a), place it in the low bit, and negate it
// (to sign extend)
// in other words, m = (a < b) ? 0 : 0xff;
m = ~(((b - a) & 0x80) >> 7) + 1;
S[i] = a &~ m | b & m;
S[255-i] = a & m | b &~ m;
}
}
void spritz_shuffle(spritz_t *sp) {
spritz_whip(sp);
spritz_crush(sp);
spritz_whip(sp);
spritz_crush(sp);
spritz_whip(sp);
A = 0;
}
#ifdef __cplusplus
}
#endif
#endif // !SPRITZ_HEADER_ONLY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment