snapkitty
october-2026-drop
c
haskell
unlambda
research
community
File size: 4,108 Bytes
d36206f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/*
 * anu_node.c — ANU Quantum Node (SEIT product recreation)
 * Copyright (C) 2026 Ahmad Ali Parr / SnapKitty Research Lab
 * SPDX-License-Identifier: LicenseRef-SEIT-FSL-Donation-1.0
 *
 * Functional source, donation-gated runtime: you may read, share, and
 * modify this source freely; running it requires a qualifying donation
 * to the licensor. See LICENSE.txt for the full terms. No warranty.
 */
/*
 * anu_node.c -- ANU Quantum Node (SEIT product recreation)
 *
 * Draws 32 bytes of entropy ("temperature") from one of two tiers:
 *
 *   Tier 1: the live Australian National University quantum random number
 *           generator JSON API. Vacuum-fluctuation-derived hex strings,
 *           fetched with curl and parsed by hand (no JSON library).
 *   Tier 2: getrandom() as the fallback. Used on ANY failure of Tier 1:
 *           curl missing or failing, network error, timeout, malformed
 *           JSON, wrong data length, non-hex characters.
 *
 * The program prints which tier supplied the bytes and the drawn bytes
 * as hex. Every run's temperature has never existed before and will
 * never exist again.
 */

#define _GNU_SOURCE /* getrandom(), popen() under -std=c11 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/random.h>

#define DRAW_BYTES 32u /* total bytes drawn per run */
#define CHUNK_LEN 16u  /* bytes per ANU hex string requested */
#define RESP_MAX 16384 /* largest ANU JSON response we accept */

#define ANU_URL "https://qrng.anu.edu.au/API/jsonI.php?length=16&type=hex"
#define CURL_CMD "curl -s --max-time 10 '" ANU_URL "'"

/* Return the nibble value of a hex digit, or -1 if not hex. */
static int hex_nibble(char c)
{
	if (c >= '0' && c <= '9')
		return c - '0';
	if (c >= 'a' && c <= 'f')
		return c - 'a' + 10;
	if (c >= 'A' && c <= 'F')
		return c - 'A' + 10;
	return -1;
}

/*
 * Attempt a Tier 1 draw: fetch DRAW_BYTES bytes worth of hex strings from
 * the live ANU QRNG JSON API. Returns 0 on success, -1 on any failure.
 * Each hex string must be exactly 2*CHUNK_LEN hex characters; the first
 * DRAW_BYTES/CHUNK_LEN strings are consumed in order.
 */
static int draw_anu(unsigned char *out, size_t n)
{
	char resp[RESP_MAX];
	FILE *fp;
	size_t len, got, need, i;
	const char *data, *p, *q;
	int status, hi, lo;

	if (n == 0 || n % CHUNK_LEN != 0)
		return -1;

	fp = popen(CURL_CMD, "r");
	if (fp == NULL)
		return -1;
	len = fread(resp, 1, sizeof(resp) - 1, fp);
	status = pclose(fp);
	if (status != 0)
		return -1;
	resp[len] = '\0';

	/* Locate the "data" array. */
	data = strstr(resp, "\"data\"");
	if (data == NULL)
		return -1;
	data = strchr(data, '[');
	if (data == NULL)
		return -1;
	p = data + 1;

	need = n / CHUNK_LEN;
	got = 0;
	for (i = 0; i < need; i++) {
		p = strchr(p, '"');
		if (p == NULL)
			return -1;
		p++;
		q = strchr(p, '"');
		if (q == NULL)
			return -1;
		if ((size_t)(q - p) != (size_t)(CHUNK_LEN * 2))
			return -1;
		for (size_t j = 0; j < CHUNK_LEN; j++) {
			hi = hex_nibble(p[2 * j]);
			lo = hex_nibble(p[2 * j + 1]);
			if (hi < 0 || lo < 0)
				return -1;
			*out++ = (unsigned char)((hi << 4) | lo);
		}
		got++;
		p = q + 1;
	}
	if (got != need)
		return -1;
	return 0;
}

/* Tier 2 draw: OS entropy via getrandom(). Returns 0/-1. */
static int draw_fallback(unsigned char *out, size_t n)
{
	size_t got = 0;

	while (got < n) {
		ssize_t r = getrandom(out + got, n - got, 0);

		if (r < 0)
			return -1;
		got += (size_t)r;
	}
	return 0;
}

/* Print bytes as lowercase hex on one line. */
static void print_hex(const unsigned char *buf, size_t n)
{
	for (size_t i = 0; i < n; i++)
		printf("%02x", buf[i]);
	printf("\n");
}

int main(void)
{
	unsigned char buf[DRAW_BYTES];
	const char *label;

	if (draw_anu(buf, sizeof(buf)) == 0) {
		label = "ANU QRNG (live)";
	} else if (draw_fallback(buf, sizeof(buf)) == 0) {
		label = "getrandom() (fallback)";
	} else {
		fprintf(stderr, "anu_node: both entropy tiers failed\n");
		return EXIT_FAILURE;
	}

	printf("source: %s\n", label);
	printf("temperature: ");
	print_hex(buf, sizeof(buf));
	return EXIT_SUCCESS;
}