Base64加密解密原理以及程式碼實現

weixin_34262482發表於2014-11-09

    1. Base64使用A--Z,a--z,0--9,+,/ 這64個字元.
    2. 編碼原理:將3個位元組轉換成4個位元組( (3 X 8) = 24 = (4 X 6) )先讀入3個位元組,每讀一個位元組,左移8位,再右移四次,每次6位,這樣就有4個位元組了.
    3. 解碼原理:將4個位元組轉換成3個位元組.先讀入4個6位(用或運算),每次左移6位,再右移3次,每次8位.這樣就還原了.

    Base64是一種非經常見的編碼規範,其作用是將二進位制序列轉換為人類可讀的ASCII字元序列,經常使用在需用通過文字協議(比方HTTP和SMTP)來傳輸二進位制資料的情況下。Base64並非一種用於安全領域的加密解密演算法(這類演算法有DES等),雖然我們有時也聽到使用Base64來加密解密的說法,但這裡所說的加密與解密實際是指編碼(encode)和解碼(decode)的過程,其變換是非常easy的,只可以避免資訊被直接識別。

   

    Base64採用了一種非常easy的編碼轉換:對於待編碼資料,以3個位元組為單位,依次取6位資料並在前面補上兩個0形成新的8位編碼,因為3*8=4*6,這樣3個位元組的輸入會變成4個位元組的輸出,長度上新增�了1/3。

上面的處理還不能保證得到的字元都是可見字元,為了達到此目的,Base64制定了一個編碼表,進行統一的轉換。碼錶的大小為2^6=64,這也是Base64名稱的由來。

                            Base64編碼表

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

    Base64編解碼演算法都非常easy,網上有非常多原始碼,這裡就不介紹了。

 

    另外另一點要注意的地方,前面提到編碼是以3個位元組為單位,當剩下的字元數量不足3個位元組時,則應使用0進行填充,對應的,輸出字元則使用'='佔位,因此編碼後輸出的文字末尾可能會出現1至2個'='。

這是一種典型的編碼轉換的處理方法,相似的可能還有UTF16與UTF8之間的轉換。 /** * /file base64.h */ #ifndef XYSSL_BASE64_H #define XYSSL_BASE64_H #define XYSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x0010 #define XYSSL_ERR_BASE64_INVALID_CHARACTER -0x0012 #ifdef __cplusplus extern "C" { #endif /** * /brief Encode a buffer into base64 format * * /param dst destination buffer * /param dlen size of the buffer * /param src source buffer * /param slen amount of data to be encoded * * /return 0 if successful, or XYSSL_ERR_BASE64_BUFFER_TOO_SMALL. * *dlen is always updated to reflect the amount * of data that has (or would have) been written. * * /note Call this function with *dlen = 0 to obtain the * required buffer size in *dlen */ int base64_encode(const unsigned char *src, int slen,unsigned char *dst, int *dlen); /** * /brief Decode a base64-formatted buffer * * /param dst destination buffer * /param dlen size of the buffer * /param src source buffer * /param slen amount of data to be decoded * * /return 0 if successful, XYSSL_ERR_BASE64_BUFFER_TOO_SMALL, or * XYSSL_ERR_BASE64_INVALID_DATA if the input data is not * correct. *dlen is always updated to reflect the amount * of data that has (or would have) been written. * * /note Call this function with *dlen = 0 to obtain the * required buffer size in *dlen */ int base64_decode(const unsigned char *src, int slen,unsigned char *dst, int *dlen); /** * /brief Checkup routine * * /return 0 if successful, or 1 if the test failed */ int base64_self_test( int verbose ); #ifdef __cplusplus } #endif class CBase64 { public: CBase64(); virtual ~CBase64(); static BOOL Encrypt(const unsigned char *pSrc,int iSlen,unsigned char *pDst,int *iDlen,CString &strErrorInfo); static BOOL Decrypt(const unsigned char *pSrc,int iSlen,unsigned char *pDst,int *iDlen,CString &strErrorInfo); private: }; #endif /* base64.h */

 

//source file: base64.cpp /* * RFC 1521 base64 encoding/decoding * * Copyright (C) 2006-2007 Christophe Devine * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License, version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "stdafx.h" #include "base64.h" static const unsigned char base64_enc_map[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; static const unsigned char base64_dec_map[128] = { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, 127, 64, 127, 127, 127, 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, 127, 127, 127, 127, 127, 127, 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, 127, 127, 127, 127, 127 }; /* * Encode a buffer into base64 format */ int base64_encode(const unsigned char *src, int slen,unsigned char *dst, int *dlen) { int i, n; int C1, C2, C3; unsigned char *p; if( slen == 0 ) return( 0 ); n = (slen << 3) / 6; switch( (slen << 3) - (n * 6) ) { case 2: n += 3; break; case 4: n += 2; break; default: break; } if( *dlen < n + 1 ) { *dlen = n + 1; return( XYSSL_ERR_BASE64_BUFFER_TOO_SMALL ); } n = (slen / 3) * 3; for( i = 0, p = dst; i < n; i += 3 ) { C1 = *src++; C2 = *src++; C3 = *src++; *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; *p++ = base64_enc_map[C3 & 0x3F]; } if( i < slen ) { C1 = *src++; C2 = ((i + 1) < slen) ? *src++ : 0; *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; if( (i + 1) < slen ) *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; else *p++ = '='; *p++ = '='; } *dlen =static_cast<int>(p - dst); *p = 0; return( 0 ); } /* * Decode a base64-formatted buffer */ int base64_decode(const unsigned char *src, int slen,unsigned char *dst, int *dlen) { int i, j, n; unsigned long x; unsigned char *p; for( i = j = n = 0; i < slen; i++ ) { if( ( slen - i ) >= 2 && *(src+i) == '/r' && *(src+i+1) == '/n' ) continue; if(*(src+i) == '/n' ) continue; if(*(src+i) == '=' && ++j > 2 ) return( XYSSL_ERR_BASE64_INVALID_CHARACTER ); if(*(src+i) > 127 || base64_dec_map[*(src+i)] == 127 ) return( XYSSL_ERR_BASE64_INVALID_CHARACTER ); if( base64_dec_map[*(src+i)] < 64 && j != 0 ) return( XYSSL_ERR_BASE64_INVALID_CHARACTER ); n++; } if( n == 0 ) return( 0 ); n = ((n * 6) + 7) >> 3; if( *dlen < n ) { *dlen = n; return( XYSSL_ERR_BASE64_BUFFER_TOO_SMALL ); } for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) { if( *src == '/r' || *src == '/n' ) continue; j -= ( base64_dec_map[*src] == 64 ); x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); if( ++n == 4 ) { n = 0; if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); if( j > 2 ) *p++ = (unsigned char)( x ); } } *dlen =static_cast<int>(p - dst); return( 0 ); } BOOL CBase64::Encrypt(const unsigned char *pSrc,int iSlen,unsigned char *pDst,int *iDlen,CString &strErrorInfo) { strErrorInfo=_T(""); int iRet=base64_encode(pSrc,iSlen,pDst,iDlen); if(iRet==XYSSL_ERR_BASE64_BUFFER_TOO_SMALL) strErrorInfo=_T("分配的緩衝區太小!"); else if(iRet==XYSSL_ERR_BASE64_INVALID_CHARACTER) strErrorInfo=_T("無效資料!"); return iRet==0; } BOOL CBase64::Decrypt(const unsigned char *pSrc,int iSlen,unsigned char *pDst,int *iDlen,CString &strErrorInfo) { strErrorInfo=_T(""); int iRet=base64_decode(pSrc,iSlen,pDst,iDlen); if(iRet==XYSSL_ERR_BASE64_BUFFER_TOO_SMALL) strErrorInfo=_T("分配的緩衝區太小!"); else if(iRet==XYSSL_ERR_BASE64_INVALID_CHARACTER) strErrorInfo=_T("無效資料!"); return iRet==0; }

相關文章