【算法学习】探究 base64 加解密的秘密

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 编码的字符的过程。解密则是反过来。

索引表

二进制字符二进制字符二进制字符二进制字符二进制字符二进制字符二进制字符二进制字符
000000A001000I010000Q011000Y100000g101000o110000w1110004
000001B001001J010001R011001Z100001h101001p110001x1110015
000010C001010K010010S011010a100010i101010q110010y1110106
000011D001011L010011T011011b100011j101011r110011z1110117
000100E001100M010100U011100c100100k101100s11010001111008
000101F001101N010101V011101d100101l101101t11010111111019
000110G001110O010110W011110e100110m101110u1101102111110+
000111H001111P010111X011111f100111n101111v1101113111111/

加密过程详解

case 1

需要加密的字符串数组恰好是3的倍数

通过 ASCII 编码得到的字符以及其二进制表示

zl!
011110100110110000100001

通过 base64 重新对二进制编码后的字符

011110100110110000100001
emwh
case 2

需要加密的字符串数组最后还剩2个, 密文后面补上1个‘=’。

通过 ASCII 编码得到的字符以及其二进制表示

zl
011110100110110000000000

通过 base64 重新对二进制编码后的字符

011110100110110000000000
emw=
case 3

需要加密的字符串数组最后还剩1个,密文后面补上2个‘=’。

通过 ASCII 编码得到的字符以及其二进制表示

z
011110100000000000000000

通过 base64 重新对二进制编码后的字符

011110100000000000000000
eg==

其实解密就是加密的逆过程,所以就不再复述。

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值