Problemas com a função BN_bn2bin do OpenSSL
-
19-09-2019 - |
Pergunta
Eu estou tentando usar o BN_ * funções no OpenSSL. Especificamente, eu tenho o seguinte código:
#import <openssl/bn.h>
BIGNUM * num = BN_new();
BN_set_word(num, 42);
char * buffer = malloc((BN_num_bytes(num)+1) * sizeof(char));
buffer[BN_num_bytes(num)] = '\0';
int len = BN_bn2bin(num, buffer);
printf("42 in binary is %s\n", buffer);
No entanto, quando eu faço isso, eu não receber uma série de uns e zeros. Em vez disso, imprime "42 in binary is *"
. Tanto quanto eu posso dizer, e para o muito número limitado de exemplos disponíveis na Web que eu tenho em comparação isso, eu tenho implementado isso corretamente.
Todas as ideias por que ele não está funcionando?
Solução
BN_bn2bin
não cria uma string de impressão - em vez disso, ele cria uma representação que é verdadeiramente binário (ou seja, uma sequência de bits). Mais especificamente, createas uma representação big-endian do número. Desde 42 se encaixa em um byte, você começa um 0x2a byte, que é "*" em ASCII.
Se você quiser uma representação 0/1, você precisa iterar sobre todos os bytes, e fazer a impressão de si mesmo (por exemplo, com a mudança ou uma tabela de pesquisa).
Outras dicas
Aqui está um código que realmente transforma a saída BN_bn2bin
em uma seqüência de impressão, assim como a saída de BN_bn2dec
e BN_bn2hex
. É em uma biblioteca NodeJS mas é escrito em C ++ para a velocidade. Levou-me durante todo o dia e, provavelmente, não é o ideal (porque eu não tenho escrito qualquer código C ++ desde o primeiro ano de uni). Mas ele passa um monte de testes de unidade, então eu sei que funciona!
https://github.com/malcolmocean/node-bignum
if (BN_is_zero(&bignum->bignum_)) {
to = (char*) OPENSSL_malloc(2*sizeof(char));
to[0] = '0';
to[1] = '\0';
} else {
unsigned char *binary = (unsigned char*) OPENSSL_malloc(BN_num_bytes(&bignum->bignum_)*sizeof(unsigned char));
int len = BN_bn2bin(&bignum->bignum_, binary);
to = (char*) OPENSSL_malloc((len*8+2)*sizeof(char));
int offset = 0;
if (BN_is_negative(&bignum->bignum_)) {
to[0] = '-';
offset--;
}
unsigned char x = binary[0];
while (!(x & 128) && x) {
x = x << 1;
offset++;
}
for (int i = 0; i < len; i++) {
unsigned char bits = binary[i];
int j=7;
while(bits) {
if (bits & 1) {
to[8*i+j-offset] = '1';
} else {
to[8*i+j-offset] = '0';
}
bits = bits >> 1;
j--;
}
if (i > 0) {
while (j >= 0) {
to[8*i+j-offset] = '0';
j--;
}
}
}
to[8*len-offset] = '\0';
OPENSSL_free(binary);
}