Base64編碼
Base64是一種基於64個可列印字元來表示二進位制資料的表示方法。由於2的6次方等於64,所以每6個位元為一個單元,對應某個可列印字元。3個位元組有24個位元,對應於4個Base64單元,即3個位元組可由4個可列印字元來表示。它可用來作為電子郵件的傳輸編碼。在Base64中的可列印字元包括字母A-Z、a-z、數字0-9,這樣共有62個字元,此外兩個可列印符號在不同的系統中而不同
Base64演算法,ASCII碼字串 -- Base64編碼("0-9",“A-Z”,"a-z", '+')
需要把3個位元組轉換為4部分
xxxx xxxx | xxxx xxxx | xxxx xxxx
24位字串:“010011010110000101101110”的第一組6位數是“010011”,對應的十進位制數是19,我們查詢索引表發現,19對應的字元是“T”,因此,第一組6位數對應的字元就是“T”;同理,第二組6位數是“010110”,對應的十進位制數是22,查詢索引表,22對應的字元是“W”;同理,第三組6位數是“000101”,對應的十進位制是5,查表得,5對應的字元是“F”;同理,第四組6位數是“101110”,對應的十進位制是46,查表得,46對應的字元是“F”。到此,3個ASCII字元,一共24位,最後編碼成了4個ASCII字元,32位。因此,從24位到32位的轉變,使得Base64編碼的結果要比原來的值變得更大,且大1/3。因此,Base64編碼實質上就是把一個個24位元位組成的二進位制組合轉換成32位元位組成的二進位制組合。
Base64常用於在通常處理文字[資料]的場合,表示、傳輸、儲存一些二進位制資料,包括MIME的電子郵件及XML的一些複雜資料。
編碼部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Base64字元對映表
static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// Base64編碼函式
char *base64_encode(const unsigned char *input, int length) {
// 計算編碼後的長度,4 * ((length + 2) / 3) 確保每三個位元組編碼成四個字元
int enc_len = 4 * ((length + 2) / 3);
char *encoded = (char *)malloc(enc_len + 1); // 為編碼後的字串分配記憶體
if (!encoded) {
return NULL; // 如果記憶體分配失敗,返回NULL
}
int i = 0, j = 0;
unsigned char char_array_3[3], char_array_4[4];
// 迴圈遍歷輸入資料
while (length--) {
char_array_3[i++] = *(input++); // 將輸入資料分成3位元組一組
if (i == 3) {
// 將3位元組資料編碼成4個Base64字元
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; i < 4; i++) {
encoded[j++] = base64_chars[char_array_4[i]]; // 對映Base64字元
}
i = 0;
}
}
// 處理剩餘的位元組
if (i) {
for (int k = i; k < 3; k++) {
char_array_3[k] = '\0';
}
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (int k = 0; k < i + 1; k++) {
encoded[j++] = base64_chars[char_array_4[k]];
}
while (i++ < 3) {
encoded[j++] = '=';
}
}
encoded[j] = '\0'; // 新增字串結束符
return encoded;
}
解碼部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Base64字元對映表
static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 獲取Base64字元對應的值
static int base64_char_value(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return -1;
}
// Base64解碼函式
unsigned char *base64_decode(const char *input, int *output_length) {
int length = strlen(input);
int i = 0, j = 0, in = 0;
int dec_len = length / 4 * 3; // 計算解碼後的長度
unsigned char *decoded = (unsigned char *)malloc(dec_len); // 為解碼後的資料分配記憶體
if (!decoded) {
return NULL; // 如果記憶體分配失敗,返回NULL
}
unsigned char char_array_4[4], char_array_3[3];
// 迴圈遍歷輸入資料
while (length-- && (input[in] != '=') && (base64_char_value(input[in]) != -1)) {
char_array_4[i++] = input[in++];
if (i == 4) {
for (i = 0; i < 4; i++) {
char_array_4[i] = base64_char_value(char_array_4[i]);
}
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++) {
decoded[j++] = char_array_3[i]; // 將4個Base64字元解碼成3位元組資料
}
i = 0;
}
}
// 處理剩餘的字元
if (i) {
for (int k = i; k < 4; k++) {
char_array_4[k] = 0;
}
for (int k = 0; k < 4; k++) {
char_array_4[k] = base64_char_value(char_array_4[k]);
}
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (int k = 0; (k < i - 1); k++) {
decoded[j++] = char_array_3[k];
}
}
*output_length = j; // 設定解碼後的長度
return decoded;
}
僅用於學習記錄
參考:
什麼是Base64演算法?——全網最詳細講解-CSDN部落格