Avatar
Lainaa
Re: Matikkaa tietokoneella
Abezethibou kirjoitti: Eilen, 17:35
QS kirjoitti: Eilen, 17:25
Abezethibou kirjoitti: Eilen, 16:32 Se taitaa olla niin, että XOR-operaatio kahden (tai useamman) lähteen välillä ei voi parantaa laatua yli sen parhaan yksittäisen lähteen mutta se ei myöskään huononna tulosta jos lähteet ovat toisistaan riippumattomia.
Ainakin päättelemällä näin on. Esimerkiksi jos huono lähde tuottaisi koko ajan vain lukua 0, niin XOR toisen hyvän satunnaisluvun kanssa ei huononna tätä hyvää lähdettä. Päättely ei toki todistan mitään, vaan vain toteaa erään erikoistapauksen.
Sen voi todistaa Shannonin tai Min entropialla?
\(H(Z) \;\ge\; \max\bigl(H(X),\,H(Y)\bigr)\)
Näyttää tutulta, ja tuossa siis \(Z = X \oplus Y\), missä \(\oplus\) on XOR-operaatio. Todistus ei varmaankaan ole vaikea, mutta en nyt muista näitä juttuja ulkoa.

Tätä lausetta en tuossa edellä muistanut. Tuon perusteella kahden riippumattoman lähteen laatu voi parantua XOR-operaatiossa, mutta se ei ole koskaan huonompi kuin parhaan lähteen laatu.

Tuli mieleeni, että mikä olisi helppo esimerkki tästä tapauksesta \(H(X\oplus Y) > \max\bigl(H(X),\,H(Y)\bigr)\) eli siis vasemman puolen 'satunnaisuus on parempi' kuin X:n ja Y:n erikseen?
Re: Matikkaa tietokoneella
QS kirjoitti: Eilen, 17:56
Abezethibou kirjoitti: Eilen, 17:35
QS kirjoitti: Eilen, 17:25
Abezethibou kirjoitti: Eilen, 16:32 Se taitaa olla niin, että XOR-operaatio kahden (tai useamman) lähteen välillä ei voi parantaa laatua yli sen parhaan yksittäisen lähteen mutta se ei myöskään huononna tulosta jos lähteet ovat toisistaan riippumattomia.
Ainakin päättelemällä näin on. Esimerkiksi jos huono lähde tuottaisi koko ajan vain lukua 0, niin XOR toisen hyvän satunnaisluvun kanssa ei huononna tätä hyvää lähdettä. Päättely ei toki todistan mitään, vaan vain toteaa erään erikoistapauksen.
Sen voi todistaa Shannonin tai Min entropialla?
\(H(Z) \;\ge\; \max\bigl(H(X),\,H(Y)\bigr)\)
Näyttää tutulta, ja tuossa siis \(Z = X \oplus Y\), missä \(\oplus\) on XOR-operaatio. Todistus ei varmaankaan ole vaikea, mutta en nyt muista näitä juttuja ulkoa. Tuli mieleeni, että mikä olisi helppo esimerkki tapauksesta \(H(X\oplus Y) > \max\bigl(H(X),\,H(Y)\bigr)\) eli siis vasemman puolen 'satunnaisuus on parempi' kuin X:n ja Y:n erikseen?
Jaa olisiko vaikka se että ottaa kaksi toisistaan riippumatonta Bernoulli-lähdettä joissa molemmissa on pieni bias ja katsoo XOR-tuloksen entropiaa? Tarvinnee kirjoitella tätä auki jossain kohtaa. Muutamakin rivi harakanvarpaita tähän tarvitaan.
Abezethibou·daemon unimanus et unialis·abyssorum legatus·cuius nomen terram scindit. In tenebris lucet·in luce obscuratur. Per fractas alas suadet·per manum perditam ligat.
Per sigillum Beelzebub·Abezethibou inferorum·per sanguinem et ignem·responde mihi!
Avatar
Lainaa
Re: Matikkaa tietokoneella
Abezethibou kirjoitti: Eilen, 18:05
QS kirjoitti: Eilen, 17:56
Abezethibou kirjoitti: Eilen, 17:35
QS kirjoitti: Eilen, 17:25
Abezethibou kirjoitti: Eilen, 16:32 Se taitaa olla niin, että XOR-operaatio kahden (tai useamman) lähteen välillä ei voi parantaa laatua yli sen parhaan yksittäisen lähteen mutta se ei myöskään huononna tulosta jos lähteet ovat toisistaan riippumattomia.
Ainakin päättelemällä näin on. Esimerkiksi jos huono lähde tuottaisi koko ajan vain lukua 0, niin XOR toisen hyvän satunnaisluvun kanssa ei huononna tätä hyvää lähdettä. Päättely ei toki todistan mitään, vaan vain toteaa erään erikoistapauksen.
Sen voi todistaa Shannonin tai Min entropialla?
\(H(Z) \;\ge\; \max\bigl(H(X),\,H(Y)\bigr)\)
Näyttää tutulta, ja tuossa siis \(Z = X \oplus Y\), missä \(\oplus\) on XOR-operaatio. Todistus ei varmaankaan ole vaikea, mutta en nyt muista näitä juttuja ulkoa. Tuli mieleeni, että mikä olisi helppo esimerkki tapauksesta \(H(X\oplus Y) > \max\bigl(H(X),\,H(Y)\bigr)\) eli siis vasemman puolen 'satunnaisuus on parempi' kuin X:n ja Y:n erikseen?
Jaa olisiko vaikka se että ottaa kaksi toisistaan riippumatonta Bernoulli-lähdettä joissa molemmissa on pieni bias ja katsoo XOR-tuloksen entropiaa? Tarvinnee kirjoitella tätä auki jossain kohtaa. Muutamakin rivi harakanvarpaita tähän tarvitaan.
Joo. Kokeillaan 1-bittisillä satunnaisgeneraattoreilla X ja Y, jotka antavat satunnaisbitit 1 tai 0. Nuo X ja Y ovat hiukan vinksallaan siten, että X tuottaa bitit todennäköisyyksillä

\(P(X=1)=\dfrac{3}{5}\)

\(P(X=0)=\dfrac{2}{5}\)

ja Y on samalla tavalla epäkelpo

\(P(Y=1)=\dfrac{3}{5}\)

\(P(Y=0)=\dfrac{2}{5}\)

Shannonin entropiat ovat$$H(X)=H(Y)=-\sum_{i=0}^{1}P(x_i)\log_2P(x_i)=-\left(\frac{3}{5}\log_2(\frac{3}{5})+\frac{2}{5}\log_2(\frac{2}{5})\right) = 0.971$$XOR-operaattorin jälkeen todennäköisyydet \(P(0)\) ja \(P(1)\) ovat

\(P(X \oplus Y = 0) = P(X=0)\cdot P(Y=0) + P(X=1)\cdot P(Y=1) = \frac{2}{5} \cdot \frac{2}{5} + \frac{3}{5} \cdot \frac{3}{5}=\dfrac{13}{25}\)

\(P(X \oplus Y = 1) = \dfrac{12}{25}\)

Näistä saadaan edellistä kaavaa käyttämällä entropia

\(H(X \oplus Y) = 0.999\)

Tässä tapauksessa tosiaan \(H(X \oplus Y) > \max(H(X),H(Y))\), joten XOR parantaa satunnaisuutta.
Re: Matikkaa tietokoneella
QS kirjoitti: Eilen, 19:54
Abezethibou kirjoitti: Eilen, 18:05
QS kirjoitti: Eilen, 17:56
Abezethibou kirjoitti: Eilen, 17:35
QS kirjoitti: Eilen, 17:25
Abezethibou kirjoitti: Eilen, 16:32 Se taitaa olla niin, että XOR-operaatio kahden (tai useamman) lähteen välillä ei voi parantaa laatua yli sen parhaan yksittäisen lähteen mutta se ei myöskään huononna tulosta jos lähteet ovat toisistaan riippumattomia.
Ainakin päättelemällä näin on. Esimerkiksi jos huono lähde tuottaisi koko ajan vain lukua 0, niin XOR toisen hyvän satunnaisluvun kanssa ei huononna tätä hyvää lähdettä. Päättely ei toki todistan mitään, vaan vain toteaa erään erikoistapauksen.
Sen voi todistaa Shannonin tai Min entropialla?
\(H(Z) \;\ge\; \max\bigl(H(X),\,H(Y)\bigr)\)
Näyttää tutulta, ja tuossa siis \(Z = X \oplus Y\), missä \(\oplus\) on XOR-operaatio. Todistus ei varmaankaan ole vaikea, mutta en nyt muista näitä juttuja ulkoa. Tuli mieleeni, että mikä olisi helppo esimerkki tapauksesta \(H(X\oplus Y) > \max\bigl(H(X),\,H(Y)\bigr)\) eli siis vasemman puolen 'satunnaisuus on parempi' kuin X:n ja Y:n erikseen?
Jaa olisiko vaikka se että ottaa kaksi toisistaan riippumatonta Bernoulli-lähdettä joissa molemmissa on pieni bias ja katsoo XOR-tuloksen entropiaa? Tarvinnee kirjoitella tätä auki jossain kohtaa. Muutamakin rivi harakanvarpaita tähän tarvitaan.
Joo. Kokeillaan 1-bittisillä satunnaisgeneraattoreilla X ja Y, jotka antavat satunnaisbitit 1 tai 0. Nuo X ja Y ovat hiukan vinksallaan siten, että X tuottaa bitit todennäköisyyksillä

\(P(X=1)=\dfrac{3}{5}\)

\(P(X=0)=\dfrac{2}{5}\)

ja Y on samalla tavalla epäkelpo

\(P(Y=1)=\dfrac{3}{5}\)

\(P(Y=0)=\dfrac{2}{5}\)

Shannonin entropiat ovat$$H(X)=H(Y)=-\sum_{i=0}^{1}P(x_i)\log_2P(x_i)=-\left(\frac{3}{5}\log_2(\frac{3}{5})+\frac{2}{5}\log_2(\frac{2}{5})\right) = 0.971$$XOR-operaattorin jälkeen todennäköisyydet \(P(0)\) ja \(P(1)\) ovat

\(P(X \oplus Y = 0) = P(X=0)\cdot P(Y=0) + P(X=1)\cdot P(Y=1) = \frac{2}{5} \cdot \frac{2}{5} + \frac{3}{5} \cdot \frac{3}{5}=\dfrac{13}{25}\)

\(P(X \oplus Y = 1) = \dfrac{12}{25}\)

Näistä saadaan edellistä kaavaa käyttämällä entropia

\(H(X \oplus Y) = 0.999\)

Tässä tapauksessa tosiaan \(H(X \oplus Y) > \max(H(X),H(Y))\), joten XOR parantaa satunnaisuutta.
Joo tässä tapauksessa voi sanoa että XOR kannatti, mutta se on kuitenkin lineaarinen operaatio. Toisaalta helppo, nopea ja tässäkin tarkoituksessa usein käytetty. Minä olen kuitenkin päätymässä kolmeen entropialähteeseen RDSEED, TPM ja Infinite Noise TRNG usb-tikkuun. En käytä XOR:ää, vaan SHA3-512 algoritmia. Sen sisällä tehdään XOR operaatioita, mutta siellä tapahtuu paljon muutakin. Toi tikku on Suomessa lentokentällä tulossa. Ajan sille testejä kunhan saan koodin valmiiksi ja kerron täällä millaisia tuloksia saan.😀
Abezethibou·daemon unimanus et unialis·abyssorum legatus·cuius nomen terram scindit. In tenebris lucet·in luce obscuratur. Per fractas alas suadet·per manum perditam ligat.
Per sigillum Beelzebub·Abezethibou inferorum·per sanguinem et ignem·responde mihi!
Lainaa
Re: Matikkaa tietokoneella

Koodi: Valitse kaikki

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <x86intrin.h>
#include <unistd.h>
#include <fcntl.h>
#include <openssl/evp.h>

#define BUFFER_SIZE 1024
#define SALT_SIZE 32
#define MAX_RETRIES 5

static uint8_t tpm_salt[SALT_SIZE];

// Lue suola TPM:stä (esim. /dev/tpm0)
static int read_tpm_salt() {
    int fd = open("/dev/tpm0", O_RDONLY);
    if (fd == -1) {
        perror("TPM-virhe");
        return 0;
    }
    
    ssize_t bytes_read = read(fd, tpm_salt, SALT_SIZE);
    close(fd);
    
    if (bytes_read != SALT_SIZE) {
        fprintf(stderr, "Varoitus: TPM-stä luettiin vain %zd tavua\n", bytes_read);
        return 0;
    }
    return 1;
}

// Valkaise RDSEED-arvo HKDF:llä käyttäen TPM-suolaa
static int hkdf_whitening(uint64_t *val) {
    uint8_t ikm[8];  // RDSEED-avainmateriaali
    memcpy(ikm, val, sizeof(*val));
    
    uint8_t okm[8];  // Valkaistu tulos
    
    EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
    if (!ctx) return 0;

    if (EVP_PKEY_derive_init(ctx) <= 0 ||
        EVP_PKEY_CTX_set_hkdf_md(ctx, EVP_sha3_256()) <= 0 ||
        EVP_PKEY_CTX_set1_hkdf_salt(ctx, tpm_salt, SALT_SIZE) <= 0 ||
        EVP_PKEY_CTX_set1_hkdf_key(ctx, ikm, sizeof(ikm)) <= 0 ||
        EVP_PKEY_derive(ctx, okm, &(size_t){sizeof(okm)}) <= 0) {
        EVP_PKEY_CTX_free(ctx);
        return 0;
    }
    
    memcpy(val, okm, sizeof(*val));
    EVP_PKEY_CTX_free(ctx);
    return 1;
}

// Lue RDSEED laitteistolta (vain 64-bittinen versio)
static int hardware_rand(uint64_t *val) {
    for (int i = 0; i < MAX_RETRIES; ++i) {
        if (_rdseed64_step(val)) return 1;
        usleep(100 * (i + 1));
    }
    return 0;
}

int main(int argc, char *argv[]) {
    // Alusta TPM-suola
    if (!read_tpm_salt()) {
        fprintf(stderr, "Kriittinen virhe: Suolan lukeminen epäonnistui\n");
        return EXIT_FAILURE;
    }

    // Pääsilmukka
    uint64_t buffer[BUFFER_SIZE];
    size_t buf_pos = 0;
    
    while (1) {
        uint64_t val;
        if (!hardware_rand(&val) || !hkdf_whitening(&val)) {
            fprintf(stderr, "Arvon generointi epäonnistui\n");
            return EXIT_FAILURE;
        }
        
        buffer[buf_pos++] = val;
        
        if (buf_pos == BUFFER_SIZE) {
            fwrite(buffer, sizeof(uint64_t), BUFFER_SIZE, stdout);
            buf_pos = 0;
        }
    }
    
    return EXIT_SUCCESS;
}
En ole vielä testannut että kääntyykö tuo edes. Mutta ideana on hakea ensin TPM sirulta suola. Se on turkasen hidasta ja siksi se haetaan vain kerran ja käytetään samaa suolaa. Sitten käytetään SHA3-256:ta HKDF:ssä. Myöhemmin voi sitten miettiä lisää kun saan kolmannen entropian lähteen. Olen tässä miettinyt neljättäkin. Jos liitän mikrofoniliittimeen VLF vastaanottimen ja generoin satunnaislukuja radion kohinasta.😀
Abezethibou·daemon unimanus et unialis·abyssorum legatus·cuius nomen terram scindit. In tenebris lucet·in luce obscuratur. Per fractas alas suadet·per manum perditam ligat.
Per sigillum Beelzebub·Abezethibou inferorum·per sanguinem et ignem·responde mihi!
Avatar
Lainaa
Re: Matikkaa tietokoneella
Abezethibou kirjoitti: Tänään, 12:27 Olen tässä miettinyt neljättäkin. Jos liitän mikrofoniliittimeen VLF vastaanottimen ja generoin satunnaislukuja radion kohinasta.😀
Vain insinööriaivot keksivät näitä, ja mulla ei tuota kykyä ole 😄
Lainaa
Re: Matikkaa tietokoneella
Luin joskus vuosia sitten jonkun vempaimen käyttöohjeita. Olen sen jälkeenkin toki lukenut käyttöohjeita, mutta se kerta jäi mieleeni syvällisellä tavalla. Siinä ohjeessa käyttöohjeiden laatijoilla oli tapana käyttää erilaisia lyhenteitä niin paljon, että itse tekstistä ei saannut mitään selvää.

Yleensäkin vempaimien käyttöohjeet pitäisi testauttaa ennen julkaisua jollain sopivalla testijengillä, esimerkiksi vanhainkodin asukkailla, lastentarhan lapsilla, paatuneet linnakunditkin käy, jotta nähdään se, että ymmärtääkö keskivertotavis mitään niistä.

Alussa mainitsemani keissi oli tosiaankin malliesimerkki siitä, että insinöörejä ei saa koskaan päästää laatimaan käyttöohjeita, silloin kun luin sitä juttua, haaveilin siitä sitten että minusta tulisi diktaattori ja määräisin tuollaisille käyttöohjeiden "laatijoille" kuolemantuomion ampumalla tai giljotiinilla...:) 

 
SI Resurrection!
Lainaa
Re: Matikkaa tietokoneella
QS kirjoitti: Tänään, 15:10
Abezethibou kirjoitti: Tänään, 12:27 Olen tässä miettinyt neljättäkin. Jos liitän mikrofoniliittimeen VLF vastaanottimen ja generoin satunnaislukuja radion kohinasta.😀
Vain insinööriaivot keksivät näitä, ja mulla ei tuota kykyä ole 😄
Kävin eilen paikallisella kirpputorilla ja oli ihan pienestä kiinni että en ostanut vanhaa melkein taskuun mahtuvaa kuvaputkitelevisiota. Ehkä vielä ostankin jos tulee vähän halvempi vastaan. Laitan webbikameran kuvaamaan "lumisadetta" kuvaputkella ja generoin webbikameran signaalista satunnaislukuja. Noin 1% vanhan television lumisateesta on alkuperältään kosmista mikroaaltotaustasäteilyä. Loput läheisistä sähkömagneettisista häiriölähteistä, vastaanottimen analogisen elektroniikan termisestä kohinasta ja erilaisista ilmakehän häiriöistä. Varsin hyvä entropian lähde sanoisin.😀
Abezethibou·daemon unimanus et unialis·abyssorum legatus·cuius nomen terram scindit. In tenebris lucet·in luce obscuratur. Per fractas alas suadet·per manum perditam ligat.
Per sigillum Beelzebub·Abezethibou inferorum·per sanguinem et ignem·responde mihi!
Lainaa
Re: Matikkaa tietokoneella
Abezethibou kirjoitti: Tänään, 15:39
QS kirjoitti: Tänään, 15:10
Abezethibou kirjoitti: Tänään, 12:27 Olen tässä miettinyt neljättäkin. Jos liitän mikrofoniliittimeen VLF vastaanottimen ja generoin satunnaislukuja radion kohinasta.😀
Vain insinööriaivot keksivät näitä, ja mulla ei tuota kykyä ole 😄
Kävin eilen paikallisella kirpputorilla ja oli ihan pienestä kiinni että en ostanut vanhaa melkein taskuun mahtuvaa kuvaputkitelevisiota. Ehkä vielä ostankin jos tulee vähän halvempi vastaan. Laitan webbikameran kuvaamaan "lumisadetta" kuvaputkella ja generoin webbikameran signaalista satunnaislukuja. Noin 1% vanhan television lumisateesta on alkuperältään kosmista mikroaaltotaustasäteilyä. Loput läheisistä sähkömagneettisista häiriölähteistä, vastaanottimen analogisen elektroniikan termisestä kohinasta ja erilaisista ilmakehän häiriöistä. Varsin hyvä entropian lähde sanoisin.😀
Ehkei sentään entropian lähde mutta informaation lähde kuitenkin.

Muistelen esitetyn, että kun informaatiota saadaan selville, entropia vähenee. Jos kaikki informaatio saadaan selville, häviääkö entropia tyystin?

Tässä on mielenkiintoinen kysymys informaatioteorian ja termodynamiikan rajapinnasta.
 
Informaatioteoriassa entropia mittaa epävarmuutta tai tiedon puutetta. Kun saamme uutta informaatiota, epävarmuus vähenee ja samalla informaatioteoreettinen entropia pienenee. Jos tietäisimme täydellisesti kaiken mahdollisen systeemin tilan, informaatioteoreettinen entropia olisi periaatteen mukaisesti nolla.
 
Termodynamiikassa (lue: todellisuudessa) tilanne on kuitenkin monimutkaisempi. Fysikaalisissa järjestelmissä entropia liittyy systeemin mikrotilojen lukumäärään ja satunnaisuuteen. Vaikka tietäisimme kaiken järjestelmästä makroskooppisella tasolla, kvanttimekaniikan epävarmuusperiaate estää meitä tietämästä kaikkea täydellisesti mikroskooppisella tasolla.
 
Lisäksi on syytä huomata, että informaation hankkiminen itsessään vaatii energiaa ja tyypillisesti tuottaa entropiaa ympäristöön (Landauerin periaate). Informaation käsittely ja tallentaminen aiheuttavat aina vähintään teoreettisen minimimäärän entropian kasvua.
 
Joten vaikka teoreettisesti voisimme tietää "kaiken", termodynaamisessa mielessä entropia ei suinkaan häviäisi kaikkeudesta.
Hienorakennevakio vapausasteista: (1+2¹+3²+5³+1/2¹*3²/5³)⁻¹ = 137,036⁻¹
Lainaa
Re: Matikkaa tietokoneella
Tein aikani kuluksi vielä käsittääkseni NIST SP 800-90A standardin täyttävän pseudosatunnaislukugeneraattorin joka käyttää RDSEED:llä tuotettua 256 bitin siementä ja saman kokoista suolaa. Aika hyvää jälkeä tämäkin tekee. Vaatii OpenSSL 3.0+ toimiakseen. Se aina 1G välein siementää itsensä uudestaan joka on huomattavasti tiheämmin mitä standardi vaatisi. Pitää ajaa tälle vaativampia testejä kunhan tässä ehtii ja jaksaa.
kuva1.jpg
kuva1.jpg (79 KiB) Katsottu 17 kertaa
kuva2.jpg
kuva2.jpg (88.5 KiB) Katsottu 17 kertaa

Koodi: Valitse kaikki

#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <immintrin.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <errno.h>

#define BLOCK_SIZE 16 // AES-lohkon koko tavuina
#define CHUNK_BLOCKS 1024 // Lohkojen määrä per kirjoituserä (16 KB)
#define RESEED_INTERVAL (64 * 1024) // Uudelleensiemennysväli: 64 * 16 MB = 1 GB
#define SEED_SIZE 32 // 256-bittinen siemen
#define SALT_SIZE 32 // 256-bittinen suola
#define RDSEED_TIMEOUT_NS 10000000000 // 10 s aikaraja RDSEED:lle per 64 bittiä
#define LOG_FILE "aes_ctr_drbg.log" // Lokitiedoston nimi

static volatile sig_atomic_t keep_running = 1;
static EVP_CIPHER_CTX *global_ctx = NULL;
static FILE *log_file = NULL;

// Lokitusfunktio virheille (kirjoittaa lokiin ja stderr:iin)
void log_message(const char *message) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
char timestamp[32];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&ts.tv_sec));
fprintf(log_file, "[%s.%03ld] %s\n", timestamp, ts.tv_nsec / 1000000, message);
fprintf(stderr, "[%s.%03ld] %s\n", timestamp, ts.tv_nsec / 1000000, message);
fflush(log_file);
}

// Lokitusfunktio tapahtumille (kirjoittaa vain lokiin)
void log_event(const char *message) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
char timestamp[32];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&ts.tv_sec));
fprintf(log_file, "[%s.%03ld] %s\n", timestamp, ts.tv_nsec / 1000000, message);
fflush(log_file);
}

// Signaalinkäsittelijä Ctrl+C:lle
void handle_sigint(int sig) {
(void)sig;
keep_running = 0;
}

// Generoi 64-bittinen satunnaisluku RDSEED:llä
int get_random_64(unsigned long long *val) {
struct timespec start, now;
clock_gettime(CLOCK_MONOTONIC, &start);

// Yritä RDSEED:ä aikarajan puitteissa
while (1) {
if (_rdseed64_step(val) == 1) {
return 1;
}
clock_gettime(CLOCK_MONOTONIC, &now);
long elapsed_ns = (now.tv_sec - start.tv_sec) * 1000000000L + (now.tv_nsec - start.tv_nsec);
if (elapsed_ns > RDSEED_TIMEOUT_NS) {
log_message("RDSEED timeout exceeded");
return 0;
}
nanosleep(&(struct timespec){.tv_nsec = 1000000}, NULL); // 1 ms tauko
}
}

// Generoi 256-bittinen siemen ja 256-bittinen suola RDSEED:llä
int generate_seed_and_salt(uint8_t *seed, uint8_t *salt) {
// Generoi 256 bittiä siemenelle
for (int i = 0; i < SEED_SIZE / sizeof(unsigned long long); i++) {
unsigned long long val;
if (!get_random_64(&val)) {
log_message("Failed to generate seed");
return 0;
}
memcpy(seed + i * sizeof(unsigned long long), &val, sizeof(unsigned long long));
}

// Generoi 256 bittiä suolalle
for (int i = 0; i < SALT_SIZE / sizeof(unsigned long long); i++) {
unsigned long long val;
if (!get_random_64(&val)) {
log_message("Failed to generate salt");
return 0;
}
memcpy(salt + i * sizeof(unsigned long long), &val, sizeof(unsigned long long));
}
return 1;
}

// Aseta uusi siemen ja alusta laskuri
int reseed(EVP_CIPHER_CTX *ctx, uint8_t *iv) {
uint8_t seed[SEED_SIZE];
uint8_t salt[SALT_SIZE];
uint8_t key[SEED_SIZE];

// Generoi siemen ja suola
if (!generate_seed_and_salt(seed, salt)) {
return 0;
}

// Käytä HKDF:ää avaimen muodostamiseen
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
if (!kdf) {
log_message("EVP_KDF_fetch failed");
return 0;
}
EVP_KDF_CTX *kdf_ctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
if (!kdf_ctx) {
log_message("EVP_KDF_CTX_new failed");
return 0;
}

OSSL_PARAM params = {
OSSL_PARAM_construct_utf8_string("digest", "SHA256", 0),
OSSL_PARAM_construct_octet_string("salt", salt, SALT_SIZE),
OSSL_PARAM_construct_octet_string("key", seed, SEED_SIZE),
OSSL_PARAM_construct_end()
};

if (EVP_KDF_derive(kdf_ctx, key, SEED_SIZE, params) != 1) {
log_message("EVP_KDF_derive failed");
EVP_KDF_CTX_free(kdf_ctx);
return 0;
}
EVP_KDF_CTX_free(kdf_ctx);

// Nollaa laskuri (big-endian, OpenSSL hoitaa kasvattamisen)
memset(iv, 0, BLOCK_SIZE);

// Alusta EVP-konteksti
if (EVP_CIPHER_CTX_reset(ctx) != 1) {
log_message("EVP_CIPHER_CTX_reset failed");
return 0;
}
if (EVP_EncryptInit_ex2(ctx, EVP_aes_256_ctr(), key, iv, NULL) != 1) {
log_message("EVP_EncryptInit_ex2 failed");
return 0;
}

return 1;
}

int main() {
// Ohita SIGPIPE-signaali
signal(SIGPIPE, SIG_IGN);

// Avaa lokitiedosto
log_file = fopen(LOG_FILE, "a");
if (!log_file) {
fprintf(stderr, "Failed to open log file " LOG_FILE "\n");
return 1;
}
log_event("Program started");

// Asenna SIGINT-käsittelijä
signal(SIGINT, handle_sigint);

EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
log_message("EVP_CIPHER_CTX_new failed");
fclose(log_file);
return 1;
}
global_ctx = ctx;

uint8_t iv[BLOCK_SIZE] = {0}; // 128-bittinen IV (laskuri)
uint8_t buffer[CHUNK_BLOCKS * BLOCK_SIZE]; // Puskuri: 1024 * 16 = 16 KB
uint8_t zero_block[BLOCK_SIZE] = {0}; // Nollapuskuri syötteeksi
long chunk_counter = 0;

// Alusta DRBG ensimmäisellä siemenellä
if (!reseed(ctx, iv)) {
EVP_CIPHER_CTX_free(ctx);
fclose(log_file);
return 1;
}

// Generoi satunnaisdataa, kunnes keskeytetään
while (keep_running) {
// Generoi yksi 16 KB:n erä
for (int i = 0; i < CHUNK_BLOCKS && keep_running; i++) {
int outlen;
if (EVP_EncryptUpdate(ctx, &buffer[i * BLOCK_SIZE], &outlen, zero_block, BLOCK_SIZE) != 1) {
log_message("EVP_EncryptUpdate failed");
EVP_CIPHER_CTX_free(ctx);
fclose(log_file);
return 1;
}
if (outlen != BLOCK_SIZE) {
log_message("Unexpected output length");
EVP_CIPHER_CTX_free(ctx);
fclose(log_file);
return 1;
}
}

// Kirjoita erä stdout:iin
if (keep_running) {
if (fwrite(buffer, 1, sizeof(buffer), stdout) != sizeof(buffer)) {
if (errno == EPIPE) {
log_event("Output pipe closed, shutting down");
keep_running = 0;
} else {
log_message("fwrite failed");
EVP_CIPHER_CTX_free(ctx);
fclose(log_file);
return 1;
}
} else {
fflush(stdout); // Varmista kirjoitus putkeen
chunk_counter++;

// Uudelleensiemennä joka 1 GB:n jälkeen
if (chunk_counter % RESEED_INTERVAL == 0) {
if (!reseed(ctx, iv)) {
EVP_CIPHER_CTX_free(ctx);
fclose(log_file);
return 1;
}
char msg[64];
long gb_generated = (chunk_counter * CHUNK_BLOCKS * BLOCK_SIZE) / (1024LL * 1024 * 1024);
snprintf(msg, sizeof(msg), "Reseeded after %ld GB", gb_generated);
log_event(msg);
}
}
}
}

// Lokita SIGINT, jos ohjelma keskeytettiin
if (!keep_running) {
log_event("Received SIGINT, shutting down");
}

EVP_CIPHER_CTX_free(ctx);
log_event("Program terminated");
fclose(log_file);
global_ctx = NULL;
return 0;
}
Abezethibou·daemon unimanus et unialis·abyssorum legatus·cuius nomen terram scindit. In tenebris lucet·in luce obscuratur. Per fractas alas suadet·per manum perditam ligat.
Per sigillum Beelzebub·Abezethibou inferorum·per sanguinem et ignem·responde mihi!
Vastaa Viestiin