Creating ADA-CTS (Cryptographic Testing Suite)

IDEA ORIGINAL EN MI IDIOMA NATIVO

por ende bcrytpgenrandom y processprng, son seguros criptograficamente
perooo al hacer la conversion con mod

Como sabemos (BCRYPTGENRANDOM, PROCESSPRNG ETC)
son PRNGs criptograficamente seguros, por lo tanto para ellos

una ragafa de bytes de [0, 10, 50, 81, 29, 100, 110, 240, 0, 100, 30, 20, 45, 203, 231, etc]
son completamente natural y tiene alta entropia desde el punto de vista los generadores

el problema de esa rafaga de bytes completamente segura en BYTES es al mom

ento de hacer
la reduccion y busqueda con MOD

ejemplo

Charset_Only_Numbers : constant String(1 .. 10) := “0123456789”;

(0 mod 10) + 1 = 1 (10 mod 10) + 1 = 1 (50 mod 10) + 1 = 1 (81 mod 10) + 1 = 2 (29 mod 10) + 1 = 10 (100 mod 10) + 1 = 1 (110 mod 10) + 1 = 1 (240 mod 10) + 1 = 1 (0 mod 10) + 1 = 1 (100 mod 10) + 1 = 1 (30 mod 10) + 1 = 1 (20 mod 10) + 1 = 1 (45 mod 10) + 1 = 6 (203 mod 10) + 1 = 4 (231 mod 10) + 1 = 2

es un ejemplp y teoria de lo que podria pasar

FINAL_Password = 000190000000531

por lo tanto aunque los bytes sean perfectamente aleatorios
el mod podria romper esa fortaleza e introducir un patron o rachas anomalas
que podria hacer que alguien viendo muchos resultados pueda deducir los caracters futuros

como la racha de ‘0’ que hay en la cadena final



IA HELP TO TRANSLATE

As we know, kernel-level CSPRNGs (like Windows BCryptGenRandom or ProcessPrng) are cryptographically secure. From their architectural standpoint, an output burst of raw bytes like:

[0, 10, 50, 81, 29, 100, 110, 240, 0, 100, 30, 20, 45, 203, 231]

is completely natural, independent, uniform, and carries maximum entropy.

The catastrophic bottleneck occurs during the post-processing reduction phase, specifically when developers map these secure bytes into bounded human-readable alphabets using standard modulo arithmetic (mod).

Let’s say we want to generate a numeric token using a standard 10-character array:

Charset_Only_Numbers : constant String(1 .. 10) := “0123456789”;

In Ada, string arrays index from 1 .. N. If the kernel throws the perfectly valid byte stream shown above, our mathematical reduction step evaluates each item independently through isolated snapshots

(0 mod 10) + 1 = 1
(10 mod 10) + 1 = 1
(50 mod 10) + 1 = 1
(81 mod 10) + 1 = 2
(29 mod 10) + 1 = 10
(100 mod 10) + 1 = 1
(110 mod 10) + 1 = 1
(240 mod 10) + 1 = 1
(0 mod 10) + 1 = 1
(100 mod 10) + 1 = 1
(30 mod 10) + 1 = 1
(20 mod 10) + 1 = 1
(45 mod 10) + 1 = 6
(203 mod 10) + 1 = 4
(231 mod 10) + 1 = 2

When we reconstruct the final password from these indexes, we obtain:

FINAL_Password = “000190000000531”

Look at that immediate anomaly: a severe transient clustering of the character "0".

Even though the underlying OS bytes passed every randomness, hardware, and monobit test, our application-layer modulo operation completely broke the cryptographic strength of the stream by introducing anomalous runs/streaks. If an attacker captures enough of these final outputs across specific execution windows, they can observe these structural patterns, map the congruence classes, and significantly narrow down the search space to predict future character placements.



[ INFORMATION ] Charset selected => ABCDEFGHIJKLMNOPQRSTUVWXYZ
[ INFORMATION ] File size => [ 63.850778 GB ]

[ SUCCESS ] Starting test to find out charset.

Speed => 0.000000 Mb/s
Time => 0.018131500 Sec.

Character count => 6291456

Charset detected => ABCDEFGHIJKLMNOPQRSTUVWXYZ
Charset detected / Free bias => 0 .. 233

Charset by user => ABCDEFGHIJKLMNOPQRSTUVWXYZ
Charset by user / Free bias => 0 .. 233

Charset by user [Reordered] => ABCDEFGHIJKLMNOPQRSTUVWXYZ

Running New Test…

Char => ‘A’ Appear => 2636917124 => Times.
Char => ‘B’ Appear => 2636916777 => Times.
Char => ‘C’ Appear => 2636882118 => Times.
Char => ‘D’ Appear => 2636976854 => Times.
Char => ‘E’ Appear => 2636830120 => Times.
Char => ‘F’ Appear => 2636906455 => Times.
Char => ‘G’ Appear => 2636835994 => Times.
Char => ‘H’ Appear => 2636902376 => Times.
Char => ‘I’ Appear => 2636802881 => Times.
Char => ‘J’ Appear => 2636935652 => Times.
Char => ‘K’ Appear => 2636823682 => Times.
Char => ‘L’ Appear => 2636962337 => Times.
Char => ‘M’ Appear => 2636921333 => Times.
Char => ‘N’ Appear => 2636892265 => Times.
Char => ‘O’ Appear => 2636837441 => Times.
Char => ‘P’ Appear => 2636941916 => Times.
Char => ‘Q’ Appear => 2636856866 => Times.
Char => ‘R’ Appear => 2636840553 => Times.
Char => ‘S’ Appear => 2636872453 => Times.
Char => ‘T’ Appear => 2636915294 => Times.
Char => ‘U’ Appear => 2637006421 => Times.
Char => ‘V’ Appear => 2636900902 => Times.
Char => ‘W’ Appear => 2636933048 => Times.
Char => ‘X’ Appear => 2636928836 => Times.
Char => ‘Y’ Appear => 2636780404 => Times.
Char => ‘Z’ Appear => 2636930698 => Times.

Total Char Read => 68559250800

Speed => 758.218076 Mb/s
Time => 86.232706300 Sec.

Each char must appear [Count] => 2636894261.538462

Character => ‘U’ appeared => 2637006421 most times.
Character => ‘Y’ appeared => 2636780404 fewer times.

Difference between the larger and the smaller => 226017 = Percent => 0.008571

Entropy => 4.7004

Expected_Frequency => 2636894261.538462
Char => A | Componente Chi => 0.198223
Char => B | Componente Chi => 0.192251
Char => C | Componente Chi => 0.055924
Char => D | Componente Chi => 2.586950
Char => E | Componente Chi => 1.560221
Char => F | Componente Chi => 0.056385
Char => G | Componente Chi => 1.287540
Char => H | Componente Chi => 0.024970
Char => I | Componente Chi => 3.166757
Char => J | Componente Chi => 0.649692
Char => K | Componente Chi => 1.889143
Char => L | Componente Chi => 1.757472
Char => M | Componente Chi => 0.277927
Char => N | Componente Chi => 0.001512
Char => O | Componente Chi => 1.224385
Char => P | Componente Chi => 0.861221
Char => Q | Componente Chi => 0.530331
Char => R | Componente Chi => 1.093941
Char => S | Componente Chi => 0.180368
Char => T | Componente Chi => 0.167760
Char => U | Componente Chi => 4.770667
Char => V | Componente Chi => 0.016723
Char => W | Componente Chi => 0.570516
Char => X | Componente Chi => 0.453334
Char => Y | Componente Chi => 4.916215
Char => Z | Componente Chi => 0.503477

P-Value => 0.264171
Resultado => PASSED
Total Chi => 28.993904

Total Characters Swept => 68559250800

Real Observed Runs Count => 65922339695
Theoretical Expected Runs => 65922356538.346390
Average Character Run Length => 1.040000 characters/run
Sequence Oscillation Rate => 96.153822 %

Collision Probability => 0.038462
Sequence Deviation (Z-Score) => -0.334502
Calculated Runs P-Value => 0.738001

Audit Verdict => [ PASSED ]
Analysis Note => stable.

I have this implemented for the time being; I rewrote the functions NIST_Igam (A : Long_Float; X : Long_Float) return Long_Float and NIST_Igamc (A : Long_Float; X : Long_Float) return Long_Float directly from the original suite. I am still rewriting and improving parts that won’t remain in their current state.

…and therefore implement the tests—around 15 to 20 of them.
I’d love to hear your opinions, advice, or suggestions for improvements or additional implementations—or if there are any specific tests you think are necessary.

You might be interested in this interactive testsuite https://random.tastemaker.design/

Also: a link to your code would be helpful