Question

I'm trying to use the 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 don't get a string of ones 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 web that I've compared this to, I've implemented this correctly.

Any ideas why it isn't working?

Was it helpful?

Solution

BN_bn2bin doesn't create a printable string - instead, it creates a representation that is truly binary (i.e. a sequence of bits). More specifically, it createas a big-endian representation of the number. Since 42 fits into one byte, you get one byte 0x2a, which is "*" in ASCII.

If you want a 0/1 representation, you need to iterate over all bytes, and do the printing yourself (e.g. with shifting or a lookup table).

OTHER TIPS

Here's some code that actually turns the BN_bn2bin output into a printable string just like the output of BN_bn2dec and BN_bn2hex. It's in a NodeJS library but is written in C++ for speed. Took me all day and probably isn't optimal (because I haven't written any C++ code since 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);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top