日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言应用(3)——Base64编码/解码

發布時間:2023/12/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言应用(3)——Base64编码/解码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、簡介

Base64是網絡上最常見的用于傳輸8Bit字節碼的編碼方式之一,Base64就是一種基于64個可打印字符來表示二進制數據的方法。可查看RFC2045~RFC2049,上面有MIME的詳細規范。

Base64編碼是從二進制到字符的過程,可用于在HTTP環境下傳遞較長的標識信息。采用Base64編碼具有不可讀性,需要解碼后才能閱讀。

Base64由于以上優點被廣泛應用于計算機的各個領域,然而由于輸出內容中包括兩個以上“符號類”字符(+, /, =),不同的應用場景又分別研制了Base64的各種“變種”。為統一和規范化Base64的輸出,Base62x被視為無符號化的改進版本。

二、原理

這里的討論的前提是使用 UTF-8 編碼

將輸入流中的字節按每3個8bit分為一組,然后每次取6個bit,將其轉換成表格中對應的數據,如此3個字節可Base64編碼為4個字符,字節數增加三分之一。一直重復到沒有剩余的字符為止,當位數不夠時補0來滿足一個字符,且要實現編碼后的位數為4的倍數,不足的用“=”代替。

  • Base64編碼索引如下:
索引對應字符索引對應字符索引對應字符索引對應字符
0A17R34i51z
1B18S35j520
2C19T36k531
3D20U37l542
4E21V38m553
5F22W39n564
6G23X40o575
7H24Y41p586
8I25Z42q597
9J26a43r608
10K27b44s619
11L28c45t62+
12M29d46u63/
13N30e47v
14O31f48w
15P32g49x
16Q33h50y

三、示例

3.1 編碼

3.1.1 位數充足情況

  • 第一步:“S”、“.”、"H"轉換為對應的ASCII碼值分別為0x53、0x2e、0x48。
  • 第二步:轉換為對應的二進制值是01010011、00101110、01001000。由此組成一個24位的二進制字符串,這里不足8個bit的高位補0即可。
  • 第三步:將24位每6個bit分為一組,共四組。分別為 010100、110010、111001、001000。
  • 第四步:將其轉換成十進制得到,20、50、57、8。
  • 第五步:用上面的值在Base64編碼表中進行查找,分別對應:U、y、5、I。因此“S.H”Base64編碼之后就變為:Uy5I。

3.1.2 位數不足情況

只有兩字符:

  • 第一步:“S”、"H"轉換為對應的ASCII碼值分別為0x53、0x48。
  • 第二步:轉換為對應的二進制值是01010011、01001000。
  • 第三步:將每6個bit分為一組,共三組。分別為 010100、110100、1000。可以看到最后一組的比特位不足 6 個,在這種情況下,會進行末尾(低位)補0的操作。補完之后就會變成010100、110100、100000。但是你會發現,這里總共也只有18個比特,不滿足 3 個字節一組的原則。在這種情況下,前三組會按照常規的Base64進行編碼,而缺失的一組則會使用 = 來進行填充。
  • 第四步:將其轉換成十進制得到,20、52、32。
  • 第五步:用上面的值在Base64編碼表中進行查找,分別對應:U、0、g,再加上最后填充的 =。因此“SH”Base64編碼之后就變為:U0g=。

只有一字符:

  • 第一步:“S”轉換為對應的ASCII碼值分別為0x53。
  • 第二步:轉換為對應的二進制值是01010011。
  • 第三步:將每6個bit分為一組,共兩組。分別為 010100、11。可以第二組明顯不滿 6 個比特,進行低位補0操作。補完之后就會變成010100、110000。但是你會發現,這里這里只有2組,不滿四組,所以這里需要填充2個 =。
  • 第四步:將其轉換成十進制得到,20、48。
  • 第五步:用上面的值在Base64編碼表中進行查找,分別對應:U、w,再加上最后填充的2個 =。因此“S”Base64編碼之后就變為:Uw==。

3.2 解碼

因為最終的編碼產物中,如果 6 個比特的分組不滿 4 組,會有 = 作為填充物,所以一個 Base64 完后的產物總是能夠被 4 整除。

所以,在解密中,我們每次需要處理 4 個字符,將這 4 個字符編碼之后轉換成十進制,再轉換成二進制,不足 6 位的高位補0,然后將 6 個比特一組的二進制數按原順序重新分成每 8 個比特一組,也就是一個字節一組。然后將其轉換成十六進制,再轉換成對應的字符。

3.2.1 位數充足情況

  • 第一步:按照每次處理4個字符的原理,Uy5I 在編碼索引表中的值分別為20,50,57,8。
  • 第二步:將其轉換成二進制,不足六位的高位補0,再將其分成每8個bit一組,分別為01010011、00101110、01111001。
  • 第三步:將分組好的比特轉換成十六進制,得到0x53、0x2e、0x48。
  • 第四步:將十六進制轉換成字母得到,“S”、“.”、“H”,也就是 “S.H”

3.2.2 位數不足情況

  • 第一步:U0g= 在編碼索引表中的值分別為20,50,32。
  • 第二步:將其轉換成二進制,不足六位的高位補0,分別為010100、110100、100000。
  • 第三步:再將其分成每8個bit一組,分別為01010011、01001000。
  • 第四步:將分組好的比特轉換成十六進制,得到0x53、0x48。
  • 第五步:將十六進制轉換成字母得到,“S”、“H”,也就是 “SH”

四、實現

4.1 base64.h

#ifndef _BASE64_H_ #define _BASE64_H_/********************************************************************** INCLUDES*/ #include <stdint.h>/********************************************************************** API FUNCTIONS*/ uint8_t Base64_Encode(char *pInData, uint32_t inLen, char *pOutData, uint32_t *pOutLen); uint8_t Base64_Decode(char *pInData, uint32_t inLen, char *pOutData, uint32_t *pOutLen);#endif /* _BASE64_H_ */

4.2 base64.c

/********************************************************************** INCLUDES*/ #include <stdint.h> #include <stddef.h> #include "base64.h"/********************************************************************** LOCAL VARIABLES*/ static char s_base64Table[] = {'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','+', '/', '\0' };/********************************************************************** PUBLIC FUNCTIONS*/ /**@brief Base64編碼@param pInData -[in] 源字符串@param inLen -[in] 源字符串長度@param pOutData -[out] 編碼后字符串@param pOutLen -[out] 解碼后字符串長度@return 1 - 成功;0 - 失敗 */ uint8_t Base64_Encode(char *pInData, uint32_t inLen, char *pOutData, uint32_t *pOutLen) {if(NULL == pInData || 0 == inLen){return 0;}uint32_t i = 0;uint32_t j = 0;uint32_t temp = 0;// 3字節一組進行轉換for(i = 0; i < inLen; i += 3) {// 獲取第一個6位temp = (*(pInData + i) >> 2) & 0x3F;*(pOutData + j++) = s_base64Table[temp];// 獲取第二個6位的前兩位temp = (*(pInData + i) << 4) & 0x30;// 如果只有一個字符,那么需要做特殊處理if(inLen <= (i + 1)) {*(pOutData + j++) = s_base64Table[temp];*(pOutData + j++) = '=';*(pOutData + j++) = '=';break;}// 獲取第二個6位的后四位temp |= (*(pInData + i + 1) >> 4) & 0x0F;*(pOutData + j++) = s_base64Table[temp];// 獲取第三個6位的前四位temp = (*(pInData+ i + 1) << 2) & 0x3C;if(inLen <= (i + 2)){*(pOutData + j++) = s_base64Table[temp];*(pOutData + j++) = '=';break;}// 獲取第三個6位的后兩位temp |= (*(pInData + i + 2) >> 6) & 0x03;*(pOutData + j++) = s_base64Table[temp];// 獲取第四個6位temp = *(pInData + i + 2) & 0x3F;*(pOutData + j++) = s_base64Table[temp];}*(pOutData + j) = '\0';// 編碼后的長度*pOutLen = inLen * 8 / 6;return 1; }/**@brief Base64解碼@param pInData -[in] 源字符串@param inLen -[in] 源字符串長度@param pOutData -[out] 解碼后字符串@param pOutLen -[out] 解碼后字符串長度@return 1 - 成功;0 - 失敗 */ uint8_t Base64_Decode(char *pInData, uint32_t inLen, char *pOutData, uint32_t *pOutLen) {if(NULL == pInData || 0 == inLen || inLen % 4 != 0){return 0;}uint32_t i = 0;uint32_t j = 0;uint32_t k = 0;char temp[4] = "";// 4字節一組進行轉換for(i = 0; i < inLen; i += 4){// 找到在編碼索引表中對應的值for(j = 0; j < 64; j++) {if(*(pInData + i) == s_base64Table[j]){temp[0] = j;}} for(j = 0; j < 64; j++){if(*(pInData + i + 1) == s_base64Table[j]){temp[1] = j;}}for(j = 0; j < 64; j++){if(*(pInData + i + 2) == s_base64Table[j]){temp[2] = j;}}for(j = 0; j < 64; j++) {if(*(pInData + i + 3) == s_base64Table[j]) {temp[3] = j;}}// 獲取第一個6位和第二個6位的前兩位組成一個8位*(pOutData + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);if(*(pInData + i + 2) == '='){break;}// 獲取第二個6位的前四位和第三個6位的前四位組成一個8位*(pOutData + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);if(*(pInData + i + 3) == '='){break;}// 獲取第三個6位的后兩位和第四個6位組成一個8位*(pOutData + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);}*pOutLen = k;return 1; }/****************************************************END OF FILE****************************************************/

五、用法

  • 編碼:
    編碼前:a123456
    編碼后:YTEyMzQ1Ng==
#include <stdio.h> #include <string.h> #include "base64.h"int main() {char *test = "a123456";uint32_t bufLen;char *buf = (char *)malloc(sizeof(char) * 1024);memset(buf, 0, sizeof(char) * 1024);Base64_Encode(test, strlen(test), buf, &bufLen);for(int i = 0; i < bufLen; i++){printf("%c", buf[i]);}free(buf);buf = NULL;return 0; }
  • 解碼:
    解碼前:YTEyMzQ1Ng==
    解碼后:a123456
#include <stdio.h> #include <string.h> #include "base64.h"int main() {char *test = "YTEyMzQ1Ng==";uint32_t bufLen;char *buf = (char *)malloc(sizeof(char) * 1024);memset(buf, 0, sizeof(char) * 1024);Base64_Decode(test, strlen(test), buf, &bufLen);for(int i = 0; i < bufLen; i++){printf("%c", buf[i]);}free(buf);buf = NULL;return 0; }

? 由 Leung 寫于 2022 年 10 月 12 日

? 參考:Base64 原理
    C語言base64實現
    base64編碼原理及C語言實現

總結

以上是生活随笔為你收集整理的C语言应用(3)——Base64编码/解码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。