Problem with OpenSSL function BN_bn2bin
I am trying to use BN_ * functions in OpenSSL. Specifically, I have the following code:
#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);
However, when I do this, I am not getting a string of them and zeros. Instead, it prints "42 in binary is *"
. As far as I can tell, and from the very limited number of examples available on the internet that I have compared this to, I have implemented this correctly.
Any ideas why it isn't working?
source to share
BN_bn2bin
does not create a printable string - instead it creates a representation that is indeed binary (i.e. a sequence of bits). More specifically, it creates an idea of the number of people at the big end. Since 42 fits into one byte, you end up with one byte 0x2a, which is "*" in ASCII.
If you want a 0/1 representation, you need to iterate over all bytes and print yourself (for example, using a shift or lookup table).
source to share
Here is some code that actually prints the output BN_bn2bin
to a string for printing just like the output BN_bn2dec
and BN_bn2hex
. It's in the NodeJS library, but written in C ++ for speed. Was taking me all day and was probably not optimal (because I haven't written any C ++ code since the first year of uni). But it passes a bunch of unit tests, so I know it works!
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);
}
source to share