Problèmes avec la fonction BN_bn2bin de OpenSSL
-
19-09-2019 - |
Question
Je suis en train d'utiliser les BN_ * fonctions OpenSSL. Plus précisément, j'ai le code suivant:
#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);
Cependant, quand je le fais, je ne reçois pas une chaîne de uns et de zéros. Au contraire, il imprime "42 in binary is *"
. Pour autant que je peux dire, et de très nombre limité d'exemples disponibles sur le web que j'ai comparé cela, je l'ai mis en œuvre cette correctement.
Toutes les idées pourquoi il ne fonctionne pas?
La solution
BN_bn2bin
ne crée pas une chaîne imprimable - au lieu, il crée une représentation qui est vraiment binaire (à savoir une séquence de bits). Plus précisément, il createas une représentation big-endian du nombre. Etant donné que 42 s'insère dans un octet, vous obtenez un octet 0x2a, qui est « * » en ASCII.
Si vous voulez une représentation 0/1, vous devez itérer sur tous les octets, et ne vous-même l'impression (par exemple avec décalage ou une table de consultation).
Autres conseils
Voici un code qui se fait la sortie de BN_bn2bin
dans une chaîne imprimable comme la sortie de BN_bn2dec
et BN_bn2hex
. Il est dans une bibliothèque NodeJS mais il est écrit en C ++ pour la vitesse. Il m'a fallu toute la journée et est probablement pas optimale (parce que je ne l'ai pas écrit de code C ++ depuis la première année d'uni). Mais il passe un tas de tests unitaires, donc je sais que cela fonctionne!
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);
}