tags:

views:

8669

answers:

6

I have binary data in an unsigned char variable. I need to convert them to PEM base64 in c. I looked in openssl library but i could not find any function. Does any body have any idea?

+5  A: 

glib has functions for base64 encoding: http://library.gnome.org/devel/glib/2.18/glib-Base64-Encoding.html

stesch
+4  A: 

But you can also do it in openssl (openssl enc command does it....), look at the BIO_f_base64() function

Piotr Lesnicki
It seems like the OP is already using OpenSSL for some other reason, so this is probably the best way to go about it.
Josh K
+4  A: 

GNU coreutils has it in lib/base64. It's a little bloated but deals with stuff like EBCDIC. You can also play around on your own, e.g.,

char base64_digit (n) unsigned n; {
  if (n < 10) return n - '0';
  else if (n < 10 + 26) return n - 'a';
  else if (n < 10 + 26 + 26) return n - 'A';
  else assert(0);
  return 0;
}

unsigned char base64_decode_digit(char c) {
  switch (c) {
    case '=' : return 62;
    case '.' : return 63;
    default  :
      if (isdigit(c)) return c - '0';
      else if (islower(c)) return c - 'a' + 10;
      else if (isupper(c)) return c - 'A' + 10 + 26;
      else assert(0);
  }
  return 0xff;
}

unsigned base64_decode(char *s) {
  char *p;
  unsigned n = 0;

  for (p = s; *p; p++)
    n = 64 * n + base64_decode_digit(*p);

  return n;
}
Norman Ramsey
+1  A: 

Here's the decoder I've been using for years...

    static const char  table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    static const int   BASE64_INPUT_SIZE = 57;

    BOOL isbase64(char c)
    {
       return c && strchr(table, c) != NULL;
    }

    inline char value(char c)
    {
       const char *p = strchr(table, c);
       if(p) {
          return p-table;
       } else {
          return 0;
       }
    }

    int UnBase64(unsigned char *dest, const unsigned char *src, int srclen)
    {
       *dest = 0;
       if(*src == 0) 
       {
          return 0;
       }
       unsigned char *p = dest;
       do
       {

          char a = value(src[0]);
          char b = value(src[1]);
          char c = value(src[2]);
          char d = value(src[3]);
          *p++ = (a << 2) | (b >> 4);
          *p++ = (b << 4) | (c >> 2);
          *p++ = (c << 6) | d;
          if(!isbase64(src[1])) 
          {
             p -= 2;
             break;
          } 
          else if(!isbase64(src[2])) 
          {
             p -= 2;
             break;
          } 
          else if(!isbase64(src[3])) 
          {
             p--;
             break;
          }
          src += 4;
          while(*src && (*src == 13 || *src == 10)) src++;
       }
       while(srclen-= 4);
       *p = 0;
       return p-dest;
    }
LarryF
what is the *dest = 0; at the start for?
Tim
It's just a very simple operation that makes sure the dest buffer is set to NULL in case the caller did not do that before the call, and if perhaps the decode failed, the returned buffer would be zero length. I didn't say I debugged, traced, and profiled this routine, it's just one I've been using for years. :) When I look at it now, it really doesn’t need to be there, so, why don't we call it an "exercise for the reader?" hehe.. Maybe I'll just edit it out. Thanks for pointing it out!
LarryF
@LarryF, your `UnBase64` function may compromise the memory after the dest buffer, if that buffer is the exact size required to decode the base 64 encoded string. Take for instance the simple case where you try to decode the following base 64 encoded string "BQ==", into a single BYTE i.e. `unsigned char Result = 0; UnBase64(` It will corrupt the stack!
Miky Dinescu
+2  A: 

BASE64 Source Code in C

http://base64.sourceforge.net/

Daniel Silveira
A: 

Larry - could you explain what the "value" function is in your UnBase64 code sample? A C lib function I hope?

Thanks! :)

Craig
Sorry Craig.. I just noticed this, and posted the correct function in the actual post. It's an inline function that just verifies that char passed is actually in the b64 table of chars... Good catch, and my apologies for missing it...
LarryF