How to encode and decode base64 strings in C?

5

I need to encode (and decode) a JSON to be transmitted from the web to a microcontroller. The% w_that I am sending is encrypted with JSON , but cyphertext contains unprintable characters and I have some problems with this. For example, when I try to receive this data in the microcontroller the decryption does not take place correctly. However, if I encrypt and decrypt a string inside the microcontroller, the process normally occurs.

I believe the problem is character encoding because there are nonprinting characters that are not transmitted. I need to do the following steps in exactly this order:

  • Encrypt text using AES 128
  • Encode cyphertext in base64 to be transmitted via the Web
  • Receiving the data in the microcontroller
  • Decrypt cyphertext in base64, for its natural representation
  • Decrypting cyphertext using AES 128
  • My question is: how to encode and decode strings AES 128 into base64 ? Is there a library for this?

    Edit: Is there any optimized way to do this? I found an example that contains the algorithm that decodes, but it uses a huge array to do this.

        
    asked by anonymous 01.09.2016 / 04:55

    1 answer

    5

    Avelino, do not judge a code by its arrays!

    The example you found is based on the file ap_base64.c of the project APR - Apache Portable Runtime ( see here the original code ), which in turn, is very widespread and used in several other projects. It was implemented in pure C and does not depend on any other external libraries.

    This huge matrix full of magic numbers you mentioned is capable of delivering a considerable increase in data processing performance in base64 , which makes it quite feasible.

    My suggestion is: Do not be prejudiced with this code, it is fast, portable and very efficient.

    The code itself is rewritten so that it works only with ASCII:

    Header base64.h :

    /*
        base64.h
    */
    
    #ifndef __BASE64_H__
    #define __BASE64_H__
    
    int base64decode_len( const char * bufcoded );
    int base64decode( char * bufplain, const char * bufcoded );
    
    int base64encode_len( int len );
    int base64encode( char * encoded, const char * string, int len );
    
    #endif
    
    /* fim-de-arquivo */
    

    Implementation base64.c :

    /*
        base64.c
    */
    
    #include <string.h>
    
    #include "base64.h"
    
    
    static int base64decode_binary( unsigned char * bufplain, const char * bufcoded );
    static int base64encode_binary( char * encoded, const unsigned char * string, int len );
    
    
    static const char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    static const unsigned char pr2six[256] =
    {
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
        64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
        64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
    };
    
    
    static int base64decode_binary( unsigned char * bufplain, const char * bufcoded )
    {
        int nbytesdecoded;
        register const unsigned char *bufin;
        register unsigned char *bufout;
        register int nprbytes;
    
        bufin = (const unsigned char *) bufcoded;
    
        while (pr2six[*(bufin++)] <= 63);
    
        nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
        nbytesdecoded = ((nprbytes + 3) / 4) * 3;
    
        bufout = (unsigned char *) bufplain;
        bufin = (const unsigned char *) bufcoded;
    
        while (nprbytes > 4)
        {
            *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
            *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
            *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
    
            bufin += 4;
            nprbytes -= 4;
        }
    
        /* Note: (nprbytes == 1) would be an error, so just ingore that case */
        if (nprbytes > 1)
        {
            *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
        }
    
        if (nprbytes > 2)
        {
            *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
        }
    
        if (nprbytes > 3)
        {
            *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
        }
    
        *(bufout++) = '
    /*
        base64.h
    */
    
    #ifndef __BASE64_H__
    #define __BASE64_H__
    
    int base64decode_len( const char * bufcoded );
    int base64decode( char * bufplain, const char * bufcoded );
    
    int base64encode_len( int len );
    int base64encode( char * encoded, const char * string, int len );
    
    #endif
    
    /* fim-de-arquivo */
    
    '; nbytesdecoded -= (4 - nprbytes) & 3; return nbytesdecoded; } static int base64encode_binary(char *encoded, const unsigned char *string, int len ) { int i; char *p; p = encoded; for (i = 0; i < len - 2; i += 3) { *p++ = basis_64[(string[i] >> 2) & 0x3F]; *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)]; *p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] & 0xC0) >> 6)]; *p++ = basis_64[string[i + 2] & 0x3F]; } if (i < len) { *p++ = basis_64[(string[i] >> 2) & 0x3F]; if (i == (len - 1)) { *p++ = basis_64[((string[i] & 0x3) << 4)]; *p++ = '='; } else { *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)]; *p++ = basis_64[((string[i + 1] & 0xF) << 2)]; } *p++ = '='; } *p++ = '
    /*
        base64.c
    */
    
    #include <string.h>
    
    #include "base64.h"
    
    
    static int base64decode_binary( unsigned char * bufplain, const char * bufcoded );
    static int base64encode_binary( char * encoded, const unsigned char * string, int len );
    
    
    static const char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    static const unsigned char pr2six[256] =
    {
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
        64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
        64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
        64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
    };
    
    
    static int base64decode_binary( unsigned char * bufplain, const char * bufcoded )
    {
        int nbytesdecoded;
        register const unsigned char *bufin;
        register unsigned char *bufout;
        register int nprbytes;
    
        bufin = (const unsigned char *) bufcoded;
    
        while (pr2six[*(bufin++)] <= 63);
    
        nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
        nbytesdecoded = ((nprbytes + 3) / 4) * 3;
    
        bufout = (unsigned char *) bufplain;
        bufin = (const unsigned char *) bufcoded;
    
        while (nprbytes > 4)
        {
            *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
            *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
            *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
    
            bufin += 4;
            nprbytes -= 4;
        }
    
        /* Note: (nprbytes == 1) would be an error, so just ingore that case */
        if (nprbytes > 1)
        {
            *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
        }
    
        if (nprbytes > 2)
        {
            *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
        }
    
        if (nprbytes > 3)
        {
            *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
        }
    
        *(bufout++) = '%pre%';
        nbytesdecoded -= (4 - nprbytes) & 3;
    
        return nbytesdecoded;
    }
    
    
    static int base64encode_binary(char *encoded, const unsigned char *string, int len )
    {
        int i;
        char *p;
    
        p = encoded;
    
        for (i = 0; i < len - 2; i += 3)
        {
            *p++ = basis_64[(string[i] >> 2) & 0x3F];
            *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
            *p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] & 0xC0) >> 6)];
            *p++ = basis_64[string[i + 2] & 0x3F];
        }
    
        if (i < len)
        {
            *p++ = basis_64[(string[i] >> 2) & 0x3F];
    
            if (i == (len - 1))
            {
                *p++ = basis_64[((string[i] & 0x3) << 4)];
                *p++ = '=';
            }
            else
            {
                *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
                *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
            }
    
            *p++ = '=';
        }
    
        *p++ = '%pre%';
    
        return p - encoded;
    }
    
    
    int base64decode_len( const char * bufcoded )
    {
        int nbytesdecoded;
        register const unsigned char *bufin;
        register int nprbytes;
    
        bufin = (const unsigned char *) bufcoded;
    
        while (pr2six[*(bufin++)] <= 63);
    
        nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
        nbytesdecoded = ((nprbytes + 3) / 4) * 3;
    
        return nbytesdecoded + 1;
    }
    
    
    int base64decode( char * bufplain, const char * bufcoded )
    {
        int len;
        len = base64decode_binary((unsigned char *) bufplain, bufcoded);
        return len;
    }
    
    
    int base64encode_len( int len )
    {
        return ((len + 2) / 3 * 4) + 1;
    }
    
    
    int base64encode( char * encoded, const char * string, int len )
    {
        return base64encode_binary(encoded, (const unsigned char *) string, len);
    }
    
    /* fim-de-arquivo */
    
    '; return p - encoded; } int base64decode_len( const char * bufcoded ) { int nbytesdecoded; register const unsigned char *bufin; register int nprbytes; bufin = (const unsigned char *) bufcoded; while (pr2six[*(bufin++)] <= 63); nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; nbytesdecoded = ((nprbytes + 3) / 4) * 3; return nbytesdecoded + 1; } int base64decode( char * bufplain, const char * bufcoded ) { int len; len = base64decode_binary((unsigned char *) bufplain, bufcoded); return len; } int base64encode_len( int len ) { return ((len + 2) / 3 * 4) + 1; } int base64encode( char * encoded, const char * string, int len ) { return base64encode_binary(encoded, (const unsigned char *) string, len); } /* fim-de-arquivo */
        
    01.09.2016 / 15:01