Jump to content

Ler dados aleatórios do "/dev/urandom" e mostrar dados lidos


PsySc0rpi0n
Go to solution Solved by Rui Carlos,

Recommended Posts

Boas.

Ainda no seguimento desta thread, estou a tentar ler 32 bytes de dados aleatórios do device /dev/urandom e guardar cada byte num array e depois mostrar cada byte na consola, mas algo está a correr mal.

Então, o que estou a fazer é criar um ponteiro para uma stream, depois abrir essa stream, e no loop for, leio byte a byte, 32 bytes do device /dev/urandom.

Depois tento imprimir cada byte, mas de vez em quando parece-me correcto e outras vezes, aparecem uns poucos de ffffff que não sei porque aparecem.

Ignorem para já a parte da biblioteca GMP que está no código.

#include <stdio.h>
#include <math.h>
#include <gmp.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    uint8_t bytes = ceil(log2(pow(2, 256) - 1) + 1) / 8;
    FILE* fpointer = NULL;
    char* data = NULL;
    mpz_t imp_val;

    mpz_init(imp_val);

    if( (data = (char*) malloc(bytes)) == NULL) {
        printf("Memory error!\n");
        exit(-1);
    }

    printf("bytes: %d\n", bytes); 

    if( (fpointer = fopen("/dev/urandom", "rb")) == NULL )
        return -1;
    rewind(fpointer);

    for(uint8_t i = 0; i < bytes; i++){
        fread(&data[i], 1, 1, fpointer);
        printf("%02x ", data[i]);
    }
    printf("\n");
    printf("Len: %ld\n", strlen(data));
    printf("Sizeof: %lu\n", sizeof(data[0]));
    mpz_import(imp_val, 32, 1, sizeof(data[0]), 0, 0, data);
    gmp_printf("Data: %Zb\n", imp_val);
    mpz_clear(imp_val);
    free(data);
    fclose(fpointer);
    return 0;
}

 

Este código dá-me outputs deste género:

$ ./randoma
bytes: 32
07 4b fffffffe ffffffd6 60 03 ffffffa0 ffffff85 ffffffdb ffffffed 24 fffffff3 58 10 48 03 60 ffffff81 33 6d fffffff1 66 59 ffffff80 ffffffb0 ffffffdc fffffff6 ffffffee 5d 3f 07 ffffffad 
Len: 32
Sizeof: 1
Data: 11111111111110011101000100000111001010101110000

 

Os dois primeiros bytes, parecem-me aceitaveis, mas depois tem dois segmentos com os tais fffffff que não sei porque é que aparecem.

Também não sei ao certo se o rewind() é mesmo necessário, ou não, mas coloquei só para descargo de consciência!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

  • Solution

Também penso que o rewind não faz sentido, caso contrário, podias ler os mesmos valores aleatórios várias vezes.

Quanto ao ffffff, acho que o problema é que tens signed chars, pelo que os valores podem ser negativos, e o printf está a converter o signed char para um signed int, que é o esperado pelo o formato %02x (na verdade penso que o x é suposto receber um unsigned, mas também parece aceitar signed).  Se declarares o array como sendo do tipo unsigned char*, deves resolver o problema.  Provavelmente também consegues resolver o problema usando %02hhx em vez de %02x.  O mais correcto até deve ser a junção das duas modificações (unsigned char e %02hhx), pois só assim os valores passados ao printf serão do tipo esperado pelo formato.

 

Algumas notas adicionais:

  • Alguma razão para leres 1 byte de cada vez, em vez de todos de uma vez?
  • Sendo que data é um array de bytes, e não propriamente uma string (com NULL no final), diria que não é boa ideia teres código como strlen(data).
  • A expressão ceil(log2(pow(2, 256) - 1) + 1) / 8 está mesmo a pedir erros numéricos 🙂
    É uma constante que provavelmente era mais seguro definir directamente no código (podias colocar a expressão como comentário).
Link to comment
Share on other sites

On 12/10/2023 at 12:56 PM, Rui Carlos said:

Também penso que o rewind não faz sentido, caso contrário, podias ler os mesmos valores aleatórios várias vezes.

Quanto ao ffffff, acho que o problema é que tens signed chars, pelo que os valores podem ser negativos, e o printf está a converter o signed char para um signed int, que é o esperado pelo o formato %02x (na verdade penso que o x é suposto receber um unsigned, mas também parece aceitar signed).  Se declarares o array como sendo do tipo unsigned char*, deves resolver o problema.  Provavelmente também consegues resolver o problema usando %02hhx em vez de %02x.  O mais correcto até deve ser a junção das duas modificações (unsigned char e %02hhx), pois só assim os valores passados ao printf serão do tipo esperado pelo formato.

 

Algumas notas adicionais:

  • Alguma razão para leres 1 byte de cada vez, em vez de todos de uma vez?
  • Sendo que data é um array de bytes, e não propriamente uma string (com NULL no final), diria que não é boa ideia teres código como strlen(data).
  • A expressão ceil(log2(pow(2, 256) - 1) + 1) / 8 está mesmo a pedir erros numéricos 🙂
    É uma constante que provavelmente era mais seguro definir directamente no código (podias colocar a expressão como comentário).

 

Inicialmente tentei ler os 32 bytes de uma vez mas aquilo deu mal e depois tentei ler byte a byte. Mas posso tentar agora voltar atrás e tentar ler de novo os 32 bytes de uma vez!

Tenho também que ir rever os especificadores porque não me recordo do maior parte deles, para o printf!

A tal expressão, sim de facto podia declarar uma macro com ela ou fazer o que dizes, colocar o valor directamente e comentar que é dali que vem o valor!

 

Falta-me ainda resolver outro problema agora com a função mpz_import() da biblioteca GMP.

 

Edited 1;

Ah, o ler byte a byte era para ser mais fácil imprimir cada byte lido. Senão como iria imprimir depois o array de bytes? Tinha que ser um for loop ou então adicionar o \0 no final do array para depois o poder imprimir como string, não?

 

Edited 2;

 

Ok, depois de alterar ali umas cenas, acho que já consegui pôr isto a funcionar:

Qualquer coisa que se possa melhorar, mandem vir:

#include <stdio.h>
#include <math.h>
#include <gmp.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#define KEYSIZE 32

int main(void) {
    FILE* fpointer = NULL;
    unsigned char* data = NULL;
    mpz_t imp_val, n, tmp;
    uint8_t i = 0;

    mpz_inits(imp_val, n, tmp, NULL);
    mpz_set_str(n, "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 0);
    mpz_sub_ui(tmp, n, 1); // tmp = n - 1 for the key generation between 0 and n - 1
    if( (data = (unsigned char*) malloc(KEYSIZE)) == NULL) {
        printf("Memory error!\n");
        exit(-1);
    }

    if( (fpointer = fopen("/dev/urandom", "rb")) == NULL )
        return -1;

    do{
        fread(data, KEYSIZE, 1, fpointer);
        mpz_import(imp_val, 1, 1, KEYSIZE, 1, 0, data);
        i++;
    }while(mpz_cmp(imp_val, tmp) > 0);
    printf("Ran %d times!\n", i);
    gmp_printf("0x%Zx\n", imp_val);

    mpz_clears(imp_val, n, tmp, NULL);
    free(data);
    fclose(fpointer);
    return 0;
}

 

Sim, ainda não alterei a tal expressão. Ainda não decidi como fazer. Se coloco o valor num define ou se declaro o valor directamente na variável!

Ah, e ainda me falta o rejection sample que só o podia fazer após recolher os dados aleatórios. É que o número que eu quero gerar tem que cumprir pelo menos uma regra! Depois coloco aqui tudo, até para isto ficar como referência minha futura!

 

Edited 2 ou 3, ou lá quantos foram:

Pronto, agora já está o código com rejection sampling e mesmo assim não tenho a certeza se não podia evitar ter que usar a variável tmp, porque a biblioteca tens funções para todas as operações matemáticas e por isso, não sei se podia fazer simpesmente n - 1 no while do loop do{} while()

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.