PsySc0rpi0n Posted December 9, 2023 at 11:46 PM Report Share #632373 Posted December 9, 2023 at 11:46 PM 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 More sharing options...
Solution Rui Carlos Posted December 10, 2023 at 12:56 PM Solution Report Share #632374 Posted December 10, 2023 at 12:56 PM 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). Rui Carlos Gonçalves Link to comment Share on other sites More sharing options...
PsySc0rpi0n Posted December 10, 2023 at 10:10 PM Author Report Share #632378 Posted December 10, 2023 at 10:10 PM (edited) 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 December 10, 2023 at 11:30 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now