C Language implementation of Base64 encoding and decoding

Source: Internet
Author: User
Tags base64 printable characters rfc stdin strcmp



Transferred from: http://www.cnblogs.com/yejianfei/archive/2013/04/06/3002838.html






Base64 is a representation of binary data based on 64 printable characters. Because of 26=64, every 6 bits is one unit, corresponding to a printable character. Three bytes total 24 bits, corresponding to 4 base64 units, i.e. 3 bytes need to be represented by 4 printable characters. It is commonly used as the transmission encoding for e-mail. Printable characters in base64 include uppercase English letters A-Z, lowercase english letters A-Z, Arabic numerals 0-9, a total of 62 characters, and two printable symbols in different systems, usually with a plus (+) and a forward slash (/). Plus "complement symbol", usually with an equal sign (=).



The full base64 definition is visible in RFC 1421 and RFC 2045. The encoded data is slightly longer than the original data for the original 4/3. In an e-mail message, a carriage return and a newline character are required for every 76 characters, as specified in RFC 822. You can estimate the length of the data after encoding is approximately 135.1% of the original.



Base64 encoding, the three of their own data, successively into a 24-bit buffer, the first to occupy their own high. If the data is less than 3 bytes, the remaining bits in the buffer are filled with 0. Then, each time the 6 (because 26=64) bit is removed, the characters in the abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/are selected as the encoded output according to their values. Continue until the full input data conversion is complete. If there are two input data left, add 1 "=" after the encoding result, and if there is a last input data, add 2 "=" after the encoding result, and if there is no data left, don't add anything. This will ensure the correctness of data restoration.



The C language source code is as follows:


/**
 * base64 encoding, decoding implementation
 * C language source code
 *
 * Note: Please compile with gcc
 *
 * Ye Jianfei
 *
 *
 *
 *  Instructions for use:
 * Command line parameter description: If there is "-d" parameter, it is base64 decoding, otherwise it is base64 encoding.
 * If there is a "-o" parameter followed by a file name, it is output to the standard output file.
 * Input is from standard input stdin and output is standard output stdout. The input and output streams can be redirected.
 *
 * base64 encoding: input any binary stream, read until the file is read (the keyboard input encounters the file end character).
 * Output base64 encoding of plain text.
 *
 * base64 decoding: input the base64 encoding of plain text, read until the file is read (the keyboard input encounters the file end character).
 * Output the original binary stream.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <io.h>
#include <fcntl.h>
#include <stdbool.h>

#ifndef MAX_PATH
#define MAX_PATH 256
#endif

Const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

Char * base64_encode( const unsigned char * bindata, char * base64, int binlength )
{
    Int i, j;
    Unsigned char current;

    For ( i = 0, j = 0 ; i < binlength ; i += 3 )
    {
        Current = (bindata[i] >> 2) ;
        Current &= (unsigned char)0x3F;
        Base64[j++] = base64char[(int)current];

        Current = ( (unsigned char)(bindata[i] << 4 ) ) & ( (unsigned char)0x30 ) ;
        If ( i + 1 >= binlength )
        {
            Base64[j++] = base64char[(int)current];
            Base64[j++] = ‘=‘;
            Base64[j++] = ‘=‘;
            Break;
        }
        Current |= ( (unsigned char)(bindata[i+1] >> 4) ) & ( (unsigned char) 0x0F );
        Base64[j++] = base64char[(int)current];

        Current = ( (unsigned char)(bindata[i+1] << 2) ) & ( (unsigned char)0x3C ) ;
        If ( i + 2 >= binlength )
        {
            Base64[j++] = base64char[(int)current];
            Base64[j++] = ‘=‘;
            Break;
        }
        Current |= ( (unsigned char)(bindata[i+2] >> 6) ) & ( (unsigned char) 0x03 );
        Base64[j++] = base64char[(int)current];

        Current = ( (unsigned char)bindata[i+2] ) & ( (unsigned char)0x3F ) ;
        Base64[j++] = base64char[(int)current];
    }
    Base64[j] = ‘\0’;
    Return base64;
}

Int base64_decode( const char * base64, unsigned char * bindata )
{
    Int i, j;
    Unsigned char k;
    Unsigned char temp[4];
    For ( i = 0, j = 0; base64[i] != ‘\0‘ ; i += 4 )
    {
        Memset( temp, 0xFF, sizeof(temp) );
        For ( k = 0 ; k < 64 ; k ++ )
        {
            If ( base64char[k] == base64[i] )
                Temp[0]= k;
        }
        For ( k = 0 ; k < 64 ; k ++ )
        {
            If ( base64char[k] == base64[i+1] )
                Temp[1]= k;
        }
        For ( k = 0 ; k < 64 ; k ++ )
        {
            If ( base64char[k] == base64[i+2] )
                Temp[2]= k;
        }
        For ( k = 0 ; k < 64 ; k ++ )
        {
            If ( base64char[k] == base64[i+3] )
                Temp[3]= k;
        }

        Bintagata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2))&0xFC)) |
                ((unsigned char)((unsigned char)(temp[1]>>4)&0x03));
        If ( base64[i+2] == ‘=‘ )
            Break;

        Bintagata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4))&0xF0)) |
                ((unsigned char)((unsigned char)(temp[2]>>2)&0x0F));
        If ( base64[i+3] == ‘=‘ )
            Break;

        Bintagata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6))&0xF0)) |
                ((unsigned char)(temp[3]&0x3F));
    }
    Return j;
}

Void encode(FILE * fp_in, FILE * fp_out)
{
    Unsigned char bindata[2050];
    Char base64[4096];
    Size_t bytes;
    While ( !feof( fp_in ) )
    {
        Bytes = fread( bindata, 1, 2049, fp_in );
        Base64_encode( bindata, base64, bytes );
        Fprintf( fp_out, "%s", base64 );
    }
}

Void decode(FILE * fp_in, FILE * fp_out)
{
    Int i;
    Unsigned char bindata[2050];
    Char base64[4096];
    Size_t bytes;
    While ( !feof( fp_in ) )
    {
        For ( i = 0 ; i < 2048 ; i ++ )
        {
            Base64[i] = fgetc(fp_in);
            If ( base64[i] == EOF )
                Break;
            Else if ( base64[i] == ‘\n‘ || base64[i] == ‘\r‘ )
                i --;
        }
        Bytes = base64_decode( base64, bindata );
        Fwrite( bindata, bytes, 1, fp_out );
    }
}

Void help(const char * filepath)
{
    Fprintf( stderr, "Usage: %s [-d] [input_filename] [-o output_filepath]\n", filepath );
    Fprintf( stderr, "\t-d\tdecode data\n" );
    Fprintf( stderr, "\t-o\toutput filepath\n\n" );
}

Int main(int argc, char * argv[])
{
    FILE * fp_input = NULL;
    FILE * fp_output = NULL;
    Bool isencode = true;
    Bool needHelp = false;
    Int opt = 0;
    Char input_filename[MAX_PATH] = "";
    Char output_filename[MAX_PATH] = "";

    Opterr = 0;
    While ( (opt = getopt(argc, argv, "hdo:")) != -1 )
    {
        Switch(opt)
        {
        Case ‘d’:
            Isencode = false;
            Break;
        Case ‘o‘:
            Strncpy(output_filename, optarg, sizeof(output_filename));
            Output_filename[sizeof(output_filename)-1] = ‘\0’;
            Break;
        Case ‘h’:
            needHelp = true;
Break;
        Default:
            Fprintf(stderr, "%s: invalid option -- %c\n", argv[0], optopt);
            needHelp = true;
            Break;
        }
    }
    If ( optind < argc )
    {
        Strncpy(input_filename, argv[optind], sizeof(input_filename));
        Input_filename[sizeof(input_filename)-1] = ‘\0’;
    }

    If (needHelp)
    {
        Help(argv[0]);
        Return EXIT_FAILURE;
    }

    If ( !strcmp(input_filename, "") )
    {
        Fp_input = stdin;
        If (isencode)
            _setmode( _fileno(stdin), _O_BINARY );
    }
    Else
    {
        If (isencode)
            Fp_input = fopen(input_filename, "rb");
        Else
            Fp_input = fopen(input_filename, "r");
    }
    If ( fp_input == NULL )
    {
        Fprintf(stderr, "Input file open error\n");
        Return EXIT_FAILURE;
    }

    If ( !strcmp(output_filename, "") )
    {
        Fp_output = stdout;
        If (!isencode)
            _setmode( _fileno(stdout), _O_BINARY );
    }
    Else
    {
        If (isencode)
            Fp_output = fopen(output_filename, "w");
        Else
            Fp_output = fopen(output_filename, "wb");
    }
    If ( fp_output == NULL )
    {
        Fclose(fp_input);
        Fp_input = NULL;
        Fprintf(stderr, "Output file open error\n");
        Return EXIT_FAILURE;
    }

    If (isencode)
        Encode(fp_input, fp_output);
    Else
        Decode(fp_input, fp_output);
    Fclose(fp_input);
    Fclose(fp_output);
    Fp_input = fp_output = NULL;
    Return EXIT_SUCCESS;
}  


C Language implementation of Base64 encoding and decoding


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.