File size: 4,426 Bytes
ebed3db | 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 | // seb_lattice.c
// SEB Lattice Circuit — Ahmad Ali Parr, SnapKitty Collective 2026
//
// R = GF(2^8)[x]/(x^32 + 1), irreducible poly x^8+x^4+x^3+x+1 (0x11B)
// commitment[k] = XOR_{i=0..31} K0[i]*prev[(k-i)&31]
// ^ XOR_{i=0..31} K1[i]*b[(k-i)&31]
// ^ XOR_{i=0..31} K2[i]*c[(k-i)&31]
// K0=1, K1=x, K2=x^2 => K0 is identity => tip injective
// Constant-time: no data-dependent branches
#include "seb_lattice.h"
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <io.h>
static int lattice_read_at(int fd, void *buf, size_t n, long long off) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
OVERLAPPED ov = {0};
ov.Offset = (DWORD)(off & 0xFFFFFFFF);
ov.OffsetHigh = (DWORD)((off >> 32) & 0xFFFFFFFF);
DWORD got = 0;
return ReadFile(h, buf, (DWORD)n, &got, &ov) ? (int)got : -1;
}
static int lattice_write_at(int fd, const void *buf, size_t n, long long off) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
OVERLAPPED ov = {0};
ov.Offset = (DWORD)(off & 0xFFFFFFFF);
ov.OffsetHigh = (DWORD)((off >> 32) & 0xFFFFFFFF);
DWORD wrote = 0;
return WriteFile(h, buf, (DWORD)n, &wrote, &ov) ? (int)wrote : -1;
}
static int lattice_fsync(int fd) {
return FlushFileBuffers((HANDLE)_get_osfhandle(fd)) ? 0 : -1;
}
static long long lattice_filesize(int fd) {
LARGE_INTEGER sz = {0};
return GetFileSizeEx((HANDLE)_get_osfhandle(fd), &sz) ? sz.QuadPart : -1;
}
#else
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
static int lattice_read_at(int fd, void *buf, size_t n, long long off) {
return (int)pread(fd, buf, n, (off_t)off);
}
static int lattice_write_at(int fd, const void *buf, size_t n, long long off) {
return (int)pwrite(fd, buf, n, (off_t)off);
}
static int lattice_fsync(int fd) { return fdatasync(fd); }
static long long lattice_filesize(int fd) {
off_t r = lseek(fd, 0, SEEK_END);
return (r == (off_t)-1) ? -1 : (long long)r;
}
#endif
/* GF(256) multiply, AES poly 0x11B, constant-time */
static uint8_t gf256_mul(uint8_t x, uint8_t y) {
uint8_t z = 0;
for (int i = 0; i < 8; i++) {
if (y & 1) z ^= x;
uint8_t hi = x & 0x80;
x = (uint8_t)(x << 1);
if (hi) x ^= 0x1B;
y >>= 1;
}
return z;
}
/* Cyclic convolution in GF(256)[x]/(x^32+1) */
static void cyclic_convolve(const uint8_t a[32], const uint8_t b[32], uint8_t c[32]) {
for (int k = 0; k < 32; k++) {
uint8_t s = 0;
for (int i = 0; i < 32; i++)
s ^= gf256_mul(a[i], b[(k - i) & 31]);
c[k] = s;
}
}
/* K0=1 (identity), K1=x, K2=x^2 — frozen at genesis */
static const uint8_t K0[32] = { 1 };
static const uint8_t K1[32] = { 0, 1 };
static const uint8_t K2[32] = { 0, 0, 1 };
void seb_lattice_commit(const uint8_t prev[32],
const uint8_t payload[64],
uint8_t next[32])
{
uint8_t t0[32], t1[32], t2[32];
cyclic_convolve(K0, prev, t0);
cyclic_convolve(K1, payload, t1);
cyclic_convolve(K2, payload + 32, t2);
for (int i = 0; i < 32; i++)
next[i] = t0[i] ^ t1[i] ^ t2[i];
}
int seb_lattice_append(int fd, const uint8_t payload[64], uint8_t record[96])
{
uint8_t tip[32] = {0};
long long sz = lattice_filesize(fd);
if (sz < 0) return -1;
if (sz > 0 && lattice_read_at(fd, tip, 32, sz - 32) != 32) return -1;
seb_lattice_commit(tip, payload, record + 64);
memcpy(record, payload, 64);
if (lattice_write_at(fd, record, 96, sz) != 96) return -1;
return lattice_fsync(fd);
}
int seb_lattice_tip(int fd, uint8_t tip[32])
{
long long sz = lattice_filesize(fd);
if (sz < 0) return -1;
if (sz == 0) { memset(tip, 0, 32); return 0; }
return (lattice_read_at(fd, tip, 32, sz - 32) == 32) ? 0 : -1;
}
int seb_lattice_verify(int fd, seb_off_t start_offset, size_t count)
{
uint8_t expected[32] = {0};
uint8_t record[96];
long long pos = (long long)start_offset;
while (count > 0) {
int r = lattice_read_at(fd, record, 96, pos);
if (r == 0) break;
if (r != 96) return -1;
uint8_t computed[32];
seb_lattice_commit(expected, record, computed);
uint8_t diff = 0;
for (int i = 0; i < 32; i++) diff |= computed[i] ^ record[64 + i];
if (diff) return 0;
memcpy(expected, computed, 32);
pos += 96;
count--;
}
return 1;
}
|