N_ENTROPY randomness metrics regression (headless).
N_ENTROPY randomness metrics regression (headless).
#include <math.h>
#include <string.h>
static void approx(
const char* label,
double got,
double want,
double tol) {
if (fabs(got - want) > tol) {
n_log(
LOG_ERR,
"%s: got %.4f, expected %.4f", label, got, want);
}
}
unsigned char uni[256];
unsigned char same[64];
unsigned char z[8];
unsigned char f[8];
unsigned char half[8];
unsigned char two[4] = {'A', 'B', 'A', 'B'};
int i;
for (i = 0; i < 256; i++)
uni[i] = (unsigned char)i;
memset(same, 'A', sizeof(same));
}
memset(z, 0x00, sizeof(z));
memset(f, 0xFF, sizeof(f));
memset(half, 0x0F, sizeof(half));
{
static unsigned char toks[64][4];
const unsigned char* ptrs[64];
size_t t, np, nb;
unsigned int seed = 12345u;
for (t = 0; t < 64; t++) {
seed = seed * 1103515245u + 12345u;
toks[t][0] = (unsigned char)(seed >> 16);
seed = seed * 1103515245u + 12345u;
toks[t][1] = (unsigned char)(seed >> 16);
toks[t][2] = 0x42;
toks[t][3] = (unsigned char)((t % 2) ? 'a' : 'b');
ptrs[t] = toks[t];
}
if (np != 4) {
}
if (pos[2].distinct != 1) {
n_log(
LOG_ERR,
"position 2 should have a single value, got %zu", pos[2].distinct);
}
approx(
"stuck position entropy", pos[2].shannon, 0.0, 0.0001);
if (pos[3].distinct != 2) {
n_log(
LOG_ERR,
"position 3 should have two values, got %zu", pos[3].distinct);
}
approx(
"two-value position entropy", pos[3].shannon, 1.0, 0.0001);
if (pos[0].distinct < 30 || pos[0].shannon < 4.0) {
n_log(
LOG_ERR,
"position 0 should look random: %zu values, %.2f bits", pos[0].distinct, pos[0].shannon);
}
if (nb != 32) {
}
if (bits[16].ones != 0 || bits[17].ones != 64) {
n_log(
LOG_ERR,
"stuck bits misreported: %zu / %zu", bits[16].ones, bits[17].ones);
}
if (bits[17].p_value > 0.01) {
n_log(
LOG_ERR,
"a stuck bit should be significant, p=%.4f", bits[17].p_value);
}
}
{
if (p_mid < 0.3 || p_mid > 0.7) {
n_log(
LOG_ERR,
"chi p(10,10) should be mid-range, got %.4f", p_mid);
}
if (p_big > 1e-6) {
n_log(
LOG_ERR,
"chi p(200,10) should be tiny, got %.6f", p_big);
}
}
{
if (p_runs > 0.01) {
n_log(
LOG_ERR,
"runs test should reject a blocky stream, p=%.4f", p_runs);
}
}
n_log(
LOG_ERR,
"all-ones longest run should span the sample");
}
}
{
const unsigned char* one[1];
one[0] = z;
}
return 1;
}
return 0;
}
static void approx(const char *label, double got, double want, double tol)
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
#define LOG_NOTICE
normal but significant condition
size_t n_entropy_positions(const unsigned char *const *samples, size_t count, size_t sample_len, N_ENTROPY_POS *out, size_t max_out)
Per-POSITION analysis of a set of equal-length samples.
size_t n_entropy_bits(const unsigned char *const *samples, size_t count, size_t sample_len, N_ENTROPY_BIT *out, size_t max_out)
Per-BIT analysis of a set of equal-length samples.
size_t n_entropy_longest_run(const unsigned char *data, size_t len)
Length of the longest run of identical bits in the sample.
double n_entropy_shannon(const unsigned char *data, size_t len)
Shannon entropy of the byte sample, in bits per byte (0.0 .
double n_entropy_monobit(const unsigned char *data, size_t len)
Fraction of set bits in the sample (0.0 .
double n_entropy_chi_square(const unsigned char *data, size_t len)
Chi-square statistic of the byte histogram against a uniform distribution over 256 values.
double n_entropy_chi_square_p(double chi, size_t df)
Upper-tail p-value of a chi-square statistic (Wilson-Hilferty).
double n_entropy_runs_p(const unsigned char *data, size_t len)
Runs test over the sample's bit stream (NIST SP 800-22 style).
per-bit statistics across a set of equal-length samples
per-position statistics across a set of equal-length samples
Randomness/entropy metrics for byte samples (token-randomness analysis).