How do I base64 encode (decode) in C?

后端 未结 17 1843
孤城傲影
孤城傲影 2020-11-22 06:27

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

17条回答
  •  梦谈多话
    2020-11-22 06:48

    This is a decoder that is specifically written to avoid the need for a buffer, by writing directly to a putchar function. This is based on wikibook's implementation https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#C

    This is not as easy to use as other options above. However, it can be of use in embedded systems, where you want to dump a large file without allocating another large buffer to store the resultant base64 datauri string. (It's a pity that datauri does not let you specify the filename).

    void datauriBase64EncodeBufferless(int (*putchar_fcptr)(int), const char* type_strptr, const void* data_buf, const size_t dataLength)
    {
      const char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      const uint8_t *data = (const uint8_t *)data_buf;
      size_t x = 0;
      uint32_t n = 0;
      int padCount = dataLength % 3;
      uint8_t n0, n1, n2, n3;
    
      size_t outcount = 0;
      size_t line = 0;
    
      putchar_fcptr((int)'d');
      putchar_fcptr((int)'a');
      putchar_fcptr((int)'t');
      putchar_fcptr((int)'a');
      putchar_fcptr((int)':');
      outcount += 5;
    
      while (*type_strptr != '\0')
      {
        putchar_fcptr((int)*type_strptr);
        type_strptr++;
        outcount++;
      }
    
      putchar_fcptr((int)';');
      putchar_fcptr((int)'b');
      putchar_fcptr((int)'a');
      putchar_fcptr((int)'s');
      putchar_fcptr((int)'e');
      putchar_fcptr((int)'6');
      putchar_fcptr((int)'4');
      putchar_fcptr((int)',');
      outcount += 8;
    
      /* increment over the length of the string, three characters at a time */
      for (x = 0; x < dataLength; x += 3)
      {
        /* these three 8-bit (ASCII) characters become one 24-bit number */
        n = ((uint32_t)data[x]) << 16; //parenthesis needed, compiler depending on flags can do the shifting before conversion to uint32_t, resulting to 0
    
        if((x+1) < dataLength)
           n += ((uint32_t)data[x+1]) << 8;//parenthesis needed, compiler depending on flags can do the shifting before conversion to uint32_t, resulting to 0
    
        if((x+2) < dataLength)
           n += data[x+2];
    
        /* this 24-bit number gets separated into four 6-bit numbers */
        n0 = (uint8_t)(n >> 18) & 63;
        n1 = (uint8_t)(n >> 12) & 63;
        n2 = (uint8_t)(n >> 6) & 63;
        n3 = (uint8_t)n & 63;
    
        /*
         * if we have one byte available, then its encoding is spread
         * out over two characters
         */
    
        putchar_fcptr((int)base64chars[n0]);
        putchar_fcptr((int)base64chars[n1]);
        outcount += 2;
    
        /*
         * if we have only two bytes available, then their encoding is
         * spread out over three chars
         */
        if((x+1) < dataLength)
        {
          putchar_fcptr((int)base64chars[n2]);
          outcount += 1;
        }
    
        /*
         * if we have all three bytes available, then their encoding is spread
         * out over four characters
         */
        if((x+2) < dataLength)
        {
          putchar_fcptr((int)base64chars[n3]);
          outcount += 1;
        }
    
        /* Breaking up the line so it's easier to copy and paste */
        int curr_line = (outcount/80);
        if( curr_line != line )
        {
          line = curr_line;
          putchar_fcptr((int)'\r');
          putchar_fcptr((int)'\n');
        }
      }
    
      /*
      * create and add padding that is required if we did not have a multiple of 3
      * number of characters available
      */
      if (padCount > 0)
      {
        for (; padCount < 3; padCount++)
        {
          putchar_fcptr((int)'=');
        }
      }
    
      putchar_fcptr((int)'\r');
      putchar_fcptr((int)'\n');
    }
    

    Here is the test

    #include 
    #include 
    #include 
    
    int main(void)
    {
      char str[] = "test";
      datauriBase64EncodeBufferless(putchar, "text/plain;charset=utf-8", str, strlen(str));
      return 0;
    }
    

    Expected Output: data:text/plain;charset=utf-8;base64,dGVzdA==

提交回复
热议问题