大家好,今天帶來的是用C++程序設計語言來實現base64加密算法.在密碼學的學習過程中,可能會涉及到base64加密算法.base64加密算法是一種一種基於64個可打印字符來表示二進制數據的表示方法.
這是一種用6位二進制數來表示一個可打印字符的方法.由於2的6次方等於64,所以每6個位為一個單元,對應某個可打印字符。三個字節(每個字節8位)有24個位,對應於4個Base64字符,即3個字節需要用4個可打印字符來表示。在Base64中的可打印字符包括字母A-Z、a-z、數字0-9,這樣共有62個字符,此外兩個可打印符號在不同的系統中而不同,這里使用字符'+'和'/'.
base64的對應序列為"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".在剩余的不足24位的二進制數中,若剩余位數整除16(2個字節),則打印一個等號,若整除8(一個字節),則打印兩個等號.
可得,加密后的字符串長度是原來的4/3倍.
我使用的算法是將輸入的ASCII碼字符串全部轉換為二進制字符串,每個ASCII字符對應8位二進制數.然后每6位二進制數提取出來,按2為權展開,得到在base64中的序列下標,從而得到相應字符.這種方法肯定不是最簡單,最巧妙的,但是應該是比較好理解的.
在代碼實現上,有兩個關鍵的,就是轉換成二進制的函數和加密函數.
ASCII碼轉換為二進制函數
1 string deciToBin(int deci) //10進制轉2進制函數 2 { 3 4 string hexStr(8, ' ' ); 5 int Value = 0; 6 int i = 0; 7 8 for (; deci != 0; ++i, deci /= 2) 9 { 10 Value = deci % 2; 11 hexStr.at(i) = Value + '0'; 12 } 13 14 hexStr = hexStr.substr(0, i); 15 16 reverse(hexStr.begin(), hexStr.end()); 17 18 if (hexStr.length() < 8) 19 { 20 string add( 8 - hexStr.length(), '0'); 21 hexStr = add + hexStr; 22 } 23 24 return hexStr; 25 }
這個函數與前面寫過的進制轉換器中的十進制轉二進制函數基本一致,只是當二進制位數不足8位時要在前面補0來補足8位,使得對應准確.
接下來是加密函數:
1 string base64_encryption(const string in) //加密函數 2 { 3 int i = 0; //總的控制變量 4 int k = 0; //24位(4個6位)控制變量 5 const int n = in.length(); //二進制序列長度 6 string subs; //要對應輸出的子串 7 string out; //輸出結果字符串 8 string value("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); //對應字符 9 10 while (n - i >= 24) //處理完整的三個字節 11 { 12 for (k = 0; k < 4; ++k) 13 { 14 subs = in.substr( i + k * 6, 6); //取出6位 15 16 int sum = 0; 17 int j = 0; 18 19 for (auto & x : subs) 20 { 21 sum += (x - '0') * pow(2, 5 - j); 22 ++j; 23 } //得到下標 24 25 out += value.at(sum); //輸出對應字符 26 } 27 28 i += 24; //前進24位 29 30 if ( i % 76 == 0) 31 cout << endl; 32 } 33 34 if ( i != n) //處理剩下的不足24位部分 35 { 36 int charlen; //剩下的長度 37 38 if ((n - i) % 6 == 0) 39 charlen = (n - i) / 6; 40 else 41 charlen = (n - i) / 6 + 1; 42 43 for (k = 0; k < charlen; ++k) 44 { 45 subs = in.substr( i + k * 6, i + (k + 1) * 6 - 1); //取出6位 46 47 int sum = 0; 48 int j = 0; 49 50 for (auto & x : subs) 51 { 52 sum += (x - '0') * pow(2, 5 - j); 53 ++j; 54 } //得到下標 55 56 out += value.at(sum); //輸出對應字符 57 } 58 59 if ((n - i) % 16 == 0) 60 out += "="; 61 62 else 63 out += "=="; 64 65 } 66 67 return out; 68 }
這個函數思想也比較簡單,接受前面的二進制序列作為實參,每次提取出6位,按2的權展開,在base64字符序列中對應字符連接到輸出字符串中.再根據情況,添加等號.
至於解密算法,就可以看作加密算法的逆過程.排除等號,將字符在base64中出現的位置數轉換為6位二進制,在8位一個組合,按權展開,得到ASCII碼,就完成了.
解密函數:
1 string base64_decryption(const string in) 2 { 3 string value("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); 4 string out0; 5 string out1; 6 string deciToBin_6bit(int); 7 8 for( auto x = in.cbegin(); (*x) != '=' && x != in.cend(); ++x) //排除等號 9 out0 += deciToBin_6bit(value.find(*x)); 10 11 const int n = out0.length(); 12 13 for(int i = 0; i < n; i += 8) //每8位提取一次 14 { 15 string subs = out0.substr(i, 8); //提取8位 16 int j = 0; 17 int sum = 0; 18 19 for(auto &x : subs) 20 { 21 sum += (x - '0') * pow(2, 7 - j); 22 ++j; 23 } //按權展開,得到ASCII碼 24 25 out1 += static_cast<char>(sum); //轉換為相應字符 26 } 27 28 return out1; 29 30 }
十進制轉換為二進制的6位版本:
1 string deciToBin_6bit(int deci) //10進制轉2進制函數 2 { 3 4 string hexStr(6, ' ' ); 5 int Value = 0; 6 int i = 0; 7 8 for (; deci != 0; ++i, deci /= 2) 9 { 10 Value = deci % 2; 11 hexStr.at(i) = Value + '0'; 12 } 13 14 hexStr = hexStr.substr(0, i); 15 16 reverse(hexStr.begin(), hexStr.end()); 17 18 if (hexStr.length() < 6) 19 { 20 string add( 6 - hexStr.length(), '0'); 21 hexStr = add + hexStr; 22 } 23 24 return hexStr; 25 }
也可以與8位的版本寫成重載函數.
函數實現后,主函數就可以寫的比較簡潔了:
1 int main() 2 { 3 4 string input0; //存放輸入的字符 5 string input1; //存放二進制序列 6 string deciToBin_8bit(int); //十進制到二進制函數原型 7 string base64_encryption(const string); //加密函數原型 8 string base64_decryption(const string); 9 cout << "Input:" << endl; 10 cin >> input0; //輸入的ASCII碼字符串 11 cout << endl; 12 13 for ( auto &x : input0) 14 input1 += deciToBin_8bit(static_cast<int>(x)); //得到二進制序列 15 16 string out0 = base64_encryption(input1); 17 18 cout << out0 << endl; 19 20 cout<<endl; 21 22 string out1 = base64_decryption(out0); 23 24 cout << out1 << endl; 25 26 return 0; 27 }
用到的頭文件:
1 #include <iostream> 2 #include <cstdlib> 3 #include <cmath> 4 #include <algorithm> 5 #include <cctype>
編碼運行,Ok.
本人原創,謝謝大家!轉載請注明出處,謝謝合作!