C語言實現Base64編碼/解碼


Bse64是一種以64個可打印字符對二進制數據進行編碼的編碼算法。base64在對數據進行編碼時以三個8位字符型數據為一組,取這三個字符型數據的ASCII碼,然后以6位為一組組成4個新的數據,這4個新的數據有6位,所以它的最大值為2^6=64。我們以4個6位數據的十進制數從base64表中得到最終編碼后的字符。

Base64 編碼

Value Char  Value Char  Value Char  Value Char 
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

       由於base64編碼是將編碼前的3*8位數據,分解成4個6位的數據,所以經過base64編碼后的字符串長度是4的倍數。但往往我們進行編碼的數據長度並不是3的倍數,這就造成了“編碼”后的位數不為4的倍數,比如Brisk共5×8=40位,以6位為一組可以分為7組,這樣“編碼”后就有7個字符,但base64編碼后的字符長度應該是4的倍數,顯然這里就出問題了,那么怎么辦呢?前面的不可以拋棄掉,所以就只有“追加”了,所以Brisk經過base64編碼后的長度應該是8個字符,而第8個編碼后的字符是'=',再比如對單個字符a進行base64編碼,由於它的長度不是3的倍數,以3個字節為一組它只能分一組,再以6位為一位它只能分兩組,所以經過“編碼”后它的長度是2,但base64編碼后的個數應該是4的倍數,所以它的長度應該是4,所以在后面補上兩個‘=’,由於一個數求余3后有三個不同的結果,0、1、2,所以在對一個數據進行base64進行編碼后它的長度為:

(1)當進行編碼的數據長度是3的倍數時,len=strlen(str_in)/3*4;
(2)當進行編碼的數據長度不是3的倍數時,len=(strlen(str_in)/3+1)*4;

       我們以Brisk這個例子來說明一下base64編碼的過程。首先我們以3個字符為一組將Brisk進行分組Brisk被氛圍兩組:Bri 和 sk;然后我們取出這兩個分組中每個字節的ASCII碼,B:66 r:114 i:105 s:115 k:107。它們對應的二進制數為  B:01000010 r:01110010 i:01101001 s:01110011 k:01101011;

       第一組,我們以6位為一組對每一個3字節分組進行再分組就變成了010000 100111 001001 101001。所對應的十進制數是16 39 9 41,對應base64表中的結果是 Q n J p;

       第二組,011100 110110 101100(不夠補0),所以對應的十進制數是 28 54 44,對應base64表中的結果是 c 2 s,最終結果為QnJpc2s=(因為第二組“編碼”后只有三個字節)。

      解碼的過程是一個逆過程,我們將經過編碼后的字符按4個字符為一組,然后對照base64表得到相應的十進制數,再將其通過拆分和組合,組成3個8位數據,這個數據就是解碼后的數據,下面給一個c語言實現編碼和解碼的代碼。

/*base64.h*/  
#ifndef _BASE64_H  
#define _BASE64_H  
  
#include <stdlib.h>  
#include <string.h>  
  
unsigned char *base64_encode(unsigned char *str);  
  
unsigned char *bae64_decode(unsigned char *code);  
  
#endif  


/*base64.c*/  
#include "base64.h"  
  
unsigned char *base64_encode(unsigned char *str)  
{  
    long len;  
    long str_len;  
    unsigned char *res;  
    int i,j;  
//定義base64編碼表  
    unsigned char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  
//計算經過base64編碼后的字符串長度  
    str_len=strlen(str);  
    if(str_len % 3 == 0)  
        len=str_len/3*4;  
    else  
        len=(str_len/3+1)*4;  
  
    res=malloc(sizeof(unsigned char)*len+1);  
    res[len]='\0';  
  
//以3個8位字符為一組進行編碼  
    for(i=0,j=0;i<len-2;j+=3,i+=4)  
    {  
        res[i]=base64_table[str[j]>>2]; //取出第一個字符的前6位並找出對應的結果字符  
        res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; //將第一個字符的后位與第二個字符的前4位進行組合並找到對應的結果字符  
        res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; //將第二個字符的后4位與第三個字符的前2位組合並找出對應的結果字符  
        res[i+3]=base64_table[str[j+2]&0x3f]; //取出第三個字符的后6位並找出結果字符  
    }  
  
    switch(str_len % 3)  
    {  
        case 1:  
            res[i-2]='=';  
            res[i-1]='=';  
            break;  
        case 2:  
            res[i-1]='=';  
            break;  
    }  
  
    return res;  
}  
  
unsigned char *base64_decode(unsigned char *code)  
{  
//根據base64表,以字符找到對應的十進制數據  
    int table[]={0,0,0,0,0,0,0,0,0,0,0,0,
    		 0,0,0,0,0,0,0,0,0,0,0,0,
    		 0,0,0,0,0,0,0,0,0,0,0,0,
    		 0,0,0,0,0,0,0,62,0,0,0,
    		 63,52,53,54,55,56,57,58,
    		 59,60,61,0,0,0,0,0,0,0,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,0,0,0,0,0,0,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
    	       };  
    long len;  
    long str_len;  
    unsigned char *res;  
    int i,j;  
  
//計算解碼后的字符串長度  
    len=strlen(code);  
//判斷編碼后的字符串后是否有=  
    if(strstr(code,"=="))  
        str_len=len/4*3-2;  
    else if(strstr(code,"="))  
        str_len=len/4*3-1;  
    else  
        str_len=len/4;  
  
    res=malloc(sizeof(unsigned char)*str_len+1);  
    res[str_len]='\0';  
  
//以4個字符為一位進行解碼  
    for(i=0,j=0;i < len-2;j+=3,i+=4)  
    {  
        res[j]=((unsigned char)table[code[i]])<<2 | (((unsigned char)table[code[i+1]])>>4); //取出第一個字符對應base64表的十進制數的前6位與第二個字符對應base64表的十進制數的后2位進行組合  
        res[j+1]=(((unsigned char)table[code[i+1]])<<4) | (((unsigned char)table[code[i+2]])>>2); //取出第二個字符對應base64表的十進制數的后4位與第三個字符對應bas464表的十進制數的后4位進行組合  
        res[j+2]=(((unsigned char)table[code[i+2]])<<6) | ((unsigned char)table[code[i+3]]); //取出第三個字符對應base64表的十進制數的后2位與第4個字符進行組合  
    }  
  
    return res;  
  
}  



/*一個測試程序*/  
#include "base64.h"  
#include <stdio.h>  
  
int main(int argc,char **argv)  
{  
    if(strcmp(argv[1],"-d") == 0)  
        printf("%s\n",base64_decode(argv[2]));  
    else  
        printf("%s\n",base64_encode(argv[1]));  
  
    return 0;  
} 


編譯  
gcc -o test test.c base64.c

./test a123456
YTEyMzQ1Ng==


./test -d YTEyMzQ1Ng==
a123456

轉自:http://blog.163.com/lixiangqiu_9202/blog/static/5357503720140593058179/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM