-
Posts
1,018 -
Joined
-
Last visited
PsySc0rpi0n's Achievements
-
Ler dados aleatórios do "/dev/urandom" e mostrar dados lidos
PsySc0rpi0n replied to PsySc0rpi0n's topic in C
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() -
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!
-
Anyway, acho que já percebi algumas coisas, nomeadamente como se parece aquele array de words, dependendo do parâmetro size. Fiz no Calc (LibreOffice) uma visualiozação mental do que me parece que está naquele array, para size = 1 e size = 8. Agora outra questãoa me assola! 😛 Quando uso este pequeno programa para testar a minha visualização do array, não obtenho o que estava à espera. Por exemplo este código #include <stdio.h> #include <gmp.h> #include <inttypes.h> #include <stdlib.h> int main(void){ uint8_t* bin_array; uint8_t order = 1, endian = 0; size_t countp = 0, size = 1 , nails = 0; size_t numb = 8 * size - nails; size_t count = 0; mpz_t op; mpz_init(op); mpz_set_str(op, "1000", 0); countp = mpz_sizeinbase(op, 2); count = (countp + numb - 1) / numb; if((bin_array = (uint8_t*) malloc(count * size)) == NULL) return -1; mpz_export(bin_array, &countp, order, size, endian, nails, op); printf("word size = %zu\n" "return of mpz_sizeinbase() = %zu\n" "number of words produced = %zu\n", size, count, countp); for(uint8_t i = 0; i < count; i++) for(int8_t j = 7; j >= 0; j--) printf("bin_arr[%d]: %d\n", i, (bin_array[i] >> j) & 1); mpz_clear(op); return 0; } usando size = 1, obtenho ist: usando size = 8, obtenho: Não percebo porque é que com size = 8, obtenho um stream incompleto para o número 1000.
-
Ok, ignorando o code do primeiro post que parece que tinha de facto vários erros que eu entretanto fui corrigindo e passei para o Gitlab, vou-me referir, a partir de agora apenas ao código do gitlab. Não percebo porque é que a função desta biblioteca me diz que o número 723080195092 precisa de 40 words para ser escrito em binário. number_of_words = mpz_sizeinbase(pKey, 2); printf("Number of words: %d\n", number_of_words); Isto resulta em 40. Mas convertendo este número em binário no RapidTables, obtenho 1010100001011010111100000010110000010100. São 40 dígitos. Não sei se é coincidência, mas o número de words também é 40, o que me leva a pensar que mesmo que eu defina a word size para outro valor qualquer, a função mpz_sizeinbase() considera sempre words de 1 bit de tamanho. Significa que a variável binary_array[] vai ter 40 índices, de 0 a 39. Depois dei-me ao trabalho de mandar imprimir alguns indexes da variável binary_array[] e obtive resultados que não sei interpretar mas posso mostrar algo como isto: Não percebo aqueles valores!
-
Sim, tens razão na primeira e na terceira situações. Foram coisas que entretanto corrigi e não me lembrei de corrigir aqui no post, excepto a do gmp_Coord que corrigi ainda ontem. Quando às variáveis a, p, opA e opP, essas estão correctas. O a e P na declaração das funções não tem que ser igual ao nome das variáveis declaradas na função main(). Sobre a declaração das variáveis do tipo de dados que eu criei, acho que tinha que ser assim pois eu pretendo enviar os endereços de memória destas variáveis para depois as outras funções alterarem os seus valores no scope da função main(). Por fim, a declaração que fiz sem apontadores é porque esses valores são constantes. Não serão alteradas durante a execução do código. Já as outras, como referi a cima, é para os seus valores serem alterados pelas outras funções no scope da função main(). Agora, tenho outra dúvida que ainda não consegui perceber. E esta é quase existencial. Mas que imagem mental podemos fazer de um array que contem words ? Ou seja, pegando num exemplo específico, digamos que eu tenho o número 1000 (decimal). A sua representação hexadecimal é 0x3e8 e em binário é 0011 1110 1000 No código do Gitlab, na linha #96, a variábel binary_array[] é suposto conter words deste número 1000. Mas eu ainda não percebi o que é suposto estar neste array em cada índice! Porque a ideia que eu tinha era por exemplo, se eu definisse o tamanho da word como 1 (do sizeof(unsigned char)), como preciso de 10 bits para representar 1000 (decimal), então teria 10 words. Uma word por cada bit. Se definisse o tamanho da word como 4, estava à espera de obter 3 words de 4 bits cada (12 bits), embora neste caso tivesse os dois MSB a zero e os pudesse descartar, fazendo os 10 bits necessários para representar 1000 em binário! Mas acho que não estoua ver isto bem e aina não percebi como "visualizar" isto.
-
Ok, podia ter pensado nisso sim. Mas no caso do meu código inicial, todas as variáveis estão declaradas na função mian(), logo, para alterar essas variáveis numa função que já é chamada por outra, eu tenho que passar as referências das variáveis na funçãomain(), de função em função, certo? É esta a minha dúvida. Ou seja, eu tenho a função main() e tenho a funcA() e a funcB(). Na função main() declaro uma variável (ponteiro para...). Só vou precisar desta variável alterada dentro da funcB() que por sua vez é chamada pela funcA(). Neste cenário, eu tenho que passar o endereço de memória da variável declarada na main() para a funcA() e depois para a funcB(), certo? Quanto ao código inicial, não tem erros nenhuns. Eu é que só ali coloquei partes do código! Entretanto, coloquei o código todo no Gitlab. Se tiveres curiosidade e se quiseres ajudar quando eu precisar, é mais fácil! https://gitlab.com/PsySc0rpi0n/bitcoinexp/-/blob/master/gmp_functions.c
-
Usando aqui um exmplo mais simples que acho que consegue mostrar o mesmo que no meu post original: #include <stdio.h> void change(int* a, int* b){ *a += 1; *b += 1; } int mult(int* a, int* b){ change(a, b); return *a * (*b); } int main(){ int x = 2, y = 3; printf("a * b = %d\n", mult(&x, &y)); return 0; } Neste exemplo, eu não conseguiria enviar os endereços de memória das variáveis x e y para a função change() se não os tivesse enviado primeiro para a função mult(), certo?
-
Boas. Estou com algumas dificuldades em perceber como fazer aqui umas cenas... Tenho 3 funcções em que uma delas vai chamar as outras duas em condições específicas mas todas ou quase todas as variáveis estão criadas na função main(). Pretendo também perceber se há alguma maneira mais elegante de fazer este tipo de coisa. Uma função chamar outras duas e enviar-lhes parâmetros por referência. As 3 funções que tenho são: ecdsa_add(gmp_coord pointA, gmp_coord pointB, gmp_coord* newPointAplusB, mpz_t opA, mpz_t opP); ecdsa_double(gmp_coord point, gmp_coord* pointDouble, mpz_t opA, mpz_t opP); ecdsa_doubleadd(gmp_coord pointG, gmp_coord* newPoint, gmp_coord* newPointdoubleadd,mpz_t opA, mpz_t opP); A variável gmp_coord é definida por mim como: typedef struct{ mpz_t x; mpz_t y; }gmp_coord; Na função main() tenho declaradas todas aquelas variáveis que estão nos parâmetros das 3 funções: gmp_coord pointG, pointP, pointQ, pointG; gmp_coord* pointAdd, pointDouble, pointDoubleAdd; mpz_t opA, opP; Depois é suposto chamar estas 3 funções uma de cada vez, para já só para testar, embora dentro da ecdsa_doubleAdd() eu chame as outras duas: ecdsa_add(pointP, pointQ, &pointAdd, a, P); ecdsa_double(pointP, &pointDouble, a, P); ecdsa_doubleAdd(pointG, &pointDoubleP, &pointDoubleAdd, privKey, a, P); Agora penso que em termos de apontadores, está tudo correcto, já que eu quero alterar os seus valores na função main(), onde elas foram declaradas. A minha pergunta é: quando enviamos uma destas variáveis para dentro de uma função que por sua vez são enviados para dentro de outra função dentro da primeira função, ter as variáveis na função main() declaradas apenas como apontadores para um tipo de dados é suficiente ou tenho que as declarar como apontadores para apontadores? E há alguma forma mais elegante de "montar" estas 3 funções? É qe não sei se é muito comum enviar parâmetros para dentro de uma função que directamente ela não vai precisar deles. É só para os enviar para as funções que esta função vai chamar dentro dela!
-
Aí só pretendo verificar quando é que o i é igual a 128, através do operador % (remainder), que devolve 0 caso o i seja igual a 128. Mas já cheguei à conclusão que afinal não há bug nenhum. Segundo as especificações do protocolo I²C, no fim de um ciclo de leitura, o último byte do ciclo devolve NACK. E a função alterou um pouco: void readBytes(uint8_t intaddr, uint16_t dataln){ char singleChar; uint16_t req = 128; if(dataln <= 128){ Wire.beginTransmission(I2C_SLAVE_ADDR7); Wire.write(intaddr); Wire.endTransmission(); Wire.requestFrom(I2C_SLAVE_ADDR7, (int) (dataln)); for(uint8_t i = 0; i < dataln; i++){ singleChar = Wire.read(); Serial.print(singleChar); } }else{ for(uint8_t i = 0; i <= (dataln + i - 1) / dataln; i++){ Wire.beginTransmission(I2C_SLAVE_ADDR7); Wire.write(intaddr + i * 128); Wire.endTransmission(); Wire.requestFrom(I2C_SLAVE_ADDR7, (int) (req)); for(uint8_t j = 0; j < req; j++){ singleChar = Wire.read(); Serial.print(singleChar); } req = dataln - 128; } } }
-
Debian... Simply Debian!
-
Isso não terá a ver com o facto de teres que expecificar para que target é que vais compilar o code?
-
Boas. Estou a escrever um pequeno código para escrever e ler uma string (ou várias) numa eeprom, usando o protocolo I2C e livrarias do Arduino. O sistema é composto pelo seguinte: USB-TTL <-> ESP8266 <-> EEPROM O código completo pode ser consultado aqui. O que acontece é que a livraria Wire.h para o ESP8266 tem um buffer the 128 bytes e portanto, se a string tiver mais que 128 bytes, eu tenho que fazer a leitura por várias vezes. Ao fazer a leitura de 128 bytes em 128 bytes, o que me está a acontecer é que no 128º byte, eu recebo um NACK do I2C e embora na próxima leitura de 128 bytes eu esteja a ler este último byte que devolveu NACK e de a string estar completa, não consigo perceber porque é que neste byte 128 recebo sempre um NACK em vez de um ACK. A função que lê os bytes e os envia para a porta série é a seguinte: // Read bytes from eeprom device void readEEPROM(uint8_t intaddr, uint16_t datalen){ char singleChar; for(uint16_t i = 0; i < datalen; i++){ if(!(i % 128)){ Wire.beginTransmission(I2C_SLAVE_ADDR7); Wire.write(intaddr + i); Wire.endTransmission(); Wire.requestFrom(I2C_SLAVE_ADDR7, (int) (datalen - i)); } singleChar = Wire.read(); Serial.print(singleChar); } } Se alguém me conseguir identificar o bug, ou se me souber explicar porque é que isto acontece ou se é normal acontecer, eu agradeço. Edited; É isto que acontece:
-
@rbsrbs_dev também é preciso saber se a OP sabe o que são type casts e divisões inteiras e para que serve o 'f' e etc... Se ela não souber, estiveste a escrever chinês. 😛
-
Conheces os operadores AND, OR, etc? && é um AND. AND 0 && 0 = 0 0 && 1 = 0 1 && 1 = 1 Por outras palavras, e no contexto, significa que o loop while só repete enquanto as duas condições forem verdadeiras. Basta uma delas ser falsa e o loop pára. while(x < 100 && x > 0) { printf("Yay\n"); } Neste caso, se o valor de 'x' não estiver entre 0 e 100, o printf nunca é executado porque uma ou as duas condições falham. Para que não haja enganos, em C (e não só), uma condição veradeira é normalmente representada por um 0 e uma condição falsa é representada por um valor diferente de 0. Por exemplo, a seguinte linha de código: x = y; que é uma atribuição de um valor, neste caso o valor guardado em 'y', à variável 'x', vai devolver 0 por si só, porque a operação de atribuição irá sempre acontecer com sucesso, a não ser que um probelma muito grave de memória ou algum problema no cpu impeça a atribuição, que é o caso de uma das condições do loop while: (cur = strstr(cur, busca)) No exemplo do código do OP: char * cur = texto; while (cur < texto + texto_len && (cur = strstr(cur, busca))) { // cur e soma só são incrementados caso (cur < texxto_len) E o resultado // devolvido pela função strstr() for igual a cur cur++; soma++; }
-
Não estarás a complicar a coisa? Existe um método próprio para isso que é o getopt(). Devias dar uma olhadela nesta função!