base 加密解密
需要了解 base 加密解密,首先要了解字符编码。能够知道的是,在计算机的世界里,0和1就是全部,而目前计算机中显示的字母、数字、符号和中文等一系列其实都是通过0和1的组合,规定某个组合显示特定的字符。
通过将0和1的组合显示出字符的过程就是编码,不同的0和1的组合对应不同的字符,而这个对应关系就是该编码的索引表。而目前西文的编码就是 ASCII 编码。
所以当我们用主流的 ASCII 编码显示一段字符串的时候,如果想把它加密,那么我们应该看到的是这段字符串的二进制表现。
可以通过某种手法将这个二进制数组加工制造,那么就可以说是对这个字符串进行了加密。但是考虑到加密之后的解密,所以在加工制造的过程中,也要考虑到该加工制造需要一个可逆的过程进行解密。
base 加密解密其实可以想象成就是对一个二进制数组另一个编码的流程。
base16,base32和base64
base64 是用64(2的6次方)个特定 ASCII 字符表示256(2的8次方)个 ASCII 字符,3个 ASCII 字符经过 base64 编码后会变为4个字符,长度比原来增加1/3。密文不足4n用”=”补足。其索引表包含大写字母(A-Z),小写字母(a-z),数字(0-9)以及+/;
base32 是用32(2的5次方)个特定 ASCII 字符表示256个 ASCII 字符。5个 ASCII 字符经过 base32 编码后会变为8个字符(公约数为40),长度增加3/5。密文不足8n用“=”补足。其索引表包含大写字母(A-Z)和数字234567;
base16 是用16(2的4次方)个特定 ASCII 字符表示256个 ASCII 字符。1个 ASCII 字符经过 base16 编码后会变为2个字符,长度增加一倍。其索引表包含数字(0-9),字母(ABCDEF);
base64 详解
base64 加密其实就是将通过 ASCII 编码的字符转换成通过 base64 编码的字符的过程。解密则是反过来。
索引表
二进制 | 字符 | 二进制 | 字符 | 二进制 | 字符 | 二进制 | 字符 | 二进制 | 字符 | 二进制 | 字符 | 二进制 | 字符 | 二进制 | 字符 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
000000 | A | 001000 | I | 010000 | Q | 011000 | Y | 100000 | g | 101000 | o | 110000 | w | 111000 | 4 |
000001 | B | 001001 | J | 010001 | R | 011001 | Z | 100001 | h | 101001 | p | 110001 | x | 111001 | 5 |
000010 | C | 001010 | K | 010010 | S | 011010 | a | 100010 | i | 101010 | q | 110010 | y | 111010 | 6 |
000011 | D | 001011 | L | 010011 | T | 011011 | b | 100011 | j | 101011 | r | 110011 | z | 111011 | 7 |
000100 | E | 001100 | M | 010100 | U | 011100 | c | 100100 | k | 101100 | s | 110100 | 0 | 111100 | 8 |
000101 | F | 001101 | N | 010101 | V | 011101 | d | 100101 | l | 101101 | t | 110101 | 1 | 111101 | 9 |
000110 | G | 001110 | O | 010110 | W | 011110 | e | 100110 | m | 101110 | u | 110110 | 2 | 111110 | + |
000111 | H | 001111 | P | 010111 | X | 011111 | f | 100111 | n | 101111 | v | 110111 | 3 | 111111 | / |
加密过程详解
case 1
需要加密的字符串数组恰好是3的倍数
通过 ASCII 编码得到的字符以及其二进制表示
z | l | ! |
---|---|---|
01111010 | 01101100 | 00100001 |
通过 base64 重新对二进制编码后的字符
011110 | 100110 | 110000 | 100001 |
---|---|---|---|
e | m | w | h |
case 2
需要加密的字符串数组最后还剩2个, 密文后面补上1个‘=’。
通过 ASCII 编码得到的字符以及其二进制表示
z | l | |
---|---|---|
01111010 | 01101100 | 00000000 |
通过 base64 重新对二进制编码后的字符
011110 | 100110 | 110000 | 000000 |
---|---|---|---|
e | m | w | = |
case 3
需要加密的字符串数组最后还剩1个,密文后面补上2个‘=’。
通过 ASCII 编码得到的字符以及其二进制表示
z | ||
---|---|---|
01111010 | 00000000 | 00000000 |
通过 base64 重新对二进制编码后的字符
011110 | 100000 | 000000 | 000000 |
---|---|---|---|
e | g | = | = |
其实解密就是加密的逆过程,所以就不再复述。
C++代码
#include <iostream>
#include <string>
#include <bitset>
enum FUNCTION {BTS = 1, STB};
static const std::string BASE64 ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//get int from BASE64
int charToInt(char c) {
int res = -1;
if(c == '/') {
res = 63;
}else if(c == '+') {
res = 62;
}else if(c >= 'A' && c <= 'Z') {
res = 0 + c - 'A';
}else if(c >= 'a' && c <= 'z') {
res = 26 + c - 'a';
}else if(c >= '0' && c <= '9') {
res = 52 + c - '0';
}else if (c == '=') {
// Anyway, it will be delete at last.
res = 0;
}
return res;
}
std::string base64_decode(std::string temp) {
std::string decStr;
std::bitset<24> bitStr;
int equalSize = 0;
//change base64 char to bitset
for(int i = 0; i < 4; ++i) {
if(temp[i] == '=') equalSize++;
std::bitset<6> bit = charToInt(temp[i]);
for(int j = 0; j < 6; ++j) {
bitStr[6*(3-i) + j] = bit[j];
}
}
// std::cout << bitStr << std::endl;
//translate bit to int, then to char
for(int i = 0; i < 3; ++i) {
int binna = 0;
int B = 1;
for(int j = 0; j < 8; ++j) {
binna += B * bitStr[8*(2-i) + j];
B = B * 2;
}
decStr += binna;
}
return decStr.substr(0, 3 - equalSize);
}
void base64Tostring() {
std::string temp;
std::cout << "Please input the string for base64 decode.\n";
std::getline (std::cin, temp);
std::string resStr;
//translate 4 base64 char to 3 normal char every time.
while(temp.size() > 3) {
resStr += base64_decode(temp.substr(0,4));
temp = temp.substr(4, temp.size()-4);
}
std::cout << "base64 decode string is: " << resStr << std::endl;
}
std::string base64_encode(std::string temp, int length) {
std::string base64;
std::bitset<24> bitStr;
//change normal char to bitset
for(int i = 0; i < length; ++i) {
std::bitset<8> bit = std::bitset<8>(temp[i]);
for(int j = 0; j < 8; ++j) {
bitStr[8*(2 - i) + j] = bit[j];
}
}
// std::cout << bitStr << std::endl;
//translate bitset to int every 6 bit, and get base64 char from BASE64.
for(int i = 0; i < length + 1; ++i) {
int binna = 0;
int B = 32;
for(int j = 1; j <= 6; ++j) {
binna += B * bitStr[6*(4 -i) - j];
B = B / 2;
}
base64 += BASE64[binna];
}
return base64;
}
void stringTobase64() {
std::string temp;
std::cout << "Please input the string for base64 encode.\n";
std::getline (std::cin, temp);
std::string resStr;
//translate 3 normal char to 4 base64 char every time.
while(temp.size() > 2) {
resStr += base64_encode(temp.substr(0,3), 3);
temp = temp.substr(3, temp.size()-3);
}
//when normal string smaller than 3, add '=' at last.
if(temp.size() != 0) {
resStr += base64_encode(temp.substr(0,3), temp.size());
resStr += std::string(3-temp.size(), '=');
}
std::cout << "base64 encode string is: " << resStr << std::endl;
}
int main() {
do{
std::cout << "Please choose the function:(Input 0 means quit)"
<< "\n\t 1: base64Tostring"
<< "\n\t 2: stringTobase64"
<< "\n";
int func;
std::cin >> func;
std::cin.ignore();
if(func == 0) break;
switch (func) {
case BTS:
base64Tostring();
break;
case STB:
stringTobase64();
break;
default:
std::cout << "Wrong number.\n";
break;
}
}while (true);
return 0;
}