原理
ANSII—>Base64 : Base64_Encode
三个ANSII字符
3乘8=4乘6 思想
每个ANSII字符取值范围为 [0,128) 不超过8位字符
则每三个字符有24位对应的2进制 将这24位平均拆分4组 每组前边补00 得新串32位 平均分4份 得 小于64位的4个数对应
Base64解码表 ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’
例 “AAA” 转 Base64
A 的 ANSII码 为65 对应 2进制为 01000001
那么 AAA对应二进制010000010100000101000001
拆分4组 010000 010100 000101 000001
补00 得 00010000000101000000010100000001
再拆4份对应10进制 16 20 5 1
对应解码表 Q U F B
不足三位的情况处理
每次取前6位,不足则补零,对其到8的倍数。
例
“A” 转 Base64
A 对应2进制为 01000001
拆分补零 00010000 00010000
对应10进制 16 16
对应解码表 Q Q 补两个=
即: Q Q = =
“AA” 转 Base64
AA 对应 2进制为 0100000101000001
拆分补零 00010000 00010100 00000100
对应10进制 16 20 4
对应解码表 Q Q 补一个 =
即: Q U E =
Base64—>ANSII : Base64_Decode
同样检测=号的个数逆向转换 不做赘述
注意
没有引入其他库 仅有 bitset 用来将获取2进制表示 可自行实现
百度过C++版本 虽然可以搜到但实现好像是错的,特此贡献。
不保证代码一定没有BUG,主要传递的是思想。
转载请表明出处: https://blog.youkuaiyun.com/best335/article/details/89248692
#include<bitset>
#include<iostream>
typedef unsigned char byte;
const byte BASE64_STANDARD_ENCODE[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" };
const byte BASE64_BIN[] = { 128,64,32,16,8,4,2,1 };
std::string ByteToBin8(byte aByte) {
return std::bitset<8>(aByte).to_string();
}
byte Bin8ToByte(std::string aStr) {
byte rByte = 0;
for (int i = 0; i<8; ++i) if (aStr[i] == '1') rByte += BASE64_BIN[i];
return rByte;
}
std::string Bin8ToBin6(std::string aStr) {
return "00" + aStr.substr(0, 6) + "00" + aStr.substr(6, 6) + "00" + aStr.substr(12, 6) + "00" + aStr.substr(18, 6);
}
std::string Bin6ToBin8(std::string aStr) {
return aStr.substr(2, 6) + aStr.substr(10, 6) + aStr.substr(18, 6) + aStr.substr(26, 6);
}
std::string Encode(std::string aStr, int Type) {
std::string Bin6 = "";
switch (Type) {
case 1:
Bin6 = "00" + ByteToBin8(aStr[0]).substr(0, 6) + "00" + ByteToBin8(aStr[0]).substr(6, 2) + "00000100000001000000";
break;
case 2:
Bin6 = "00" + ByteToBin8(aStr[0]).substr(0, 6) + "00" + ByteToBin8(aStr[0]).substr(6, 2) + ByteToBin8(aStr[1]).substr(0, 4) + "00" + ByteToBin8(aStr[1]).substr(4, 4) + "0001000000";
break;
default:
Bin6 = Bin8ToBin6(ByteToBin8(aStr[0]) + ByteToBin8(aStr[1]) + ByteToBin8(aStr[2]));
break;
}
return std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(0, 8))]) +
std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(8, 8))]) +
std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(16, 8))]) +
std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(24, 8))]);
}
std::string Base64_Encode(std::string toEncode) {
std::string rStr = "";
for (int i = 0, ni = toEncode.size(); i < ni; i += 3) {
switch (ni - i)
{
case 1:
rStr += Encode(toEncode.substr(i, 1), 1);
break;
case 2:
rStr += Encode(toEncode.substr(i, 2), 2);
break;
default:
rStr += Encode(toEncode.substr(i, 3), 3);
break;
}
}
return rStr;
}
int findDict(byte b) {
for (int i = 0; i<65; ++i)
if (b == BASE64_STANDARD_ENCODE[i])
return i;
return -1;
}
std::string Decode(std::string aStr) {
std::string Bin8 = ByteToBin8(findDict(aStr[0])) + ByteToBin8(findDict(aStr[1])) + ByteToBin8(findDict(aStr[2])) + ByteToBin8(findDict(aStr[3]));
std::string rStr = "";
if (Bin8[17] == '1') {
Bin8 = Bin8.substr(2, 6) + Bin8.substr(10, 2);
rStr = std::string(1, Bin8ToByte(Bin8));
}
else if (Bin8[25] == '1') {
Bin8 = Bin8.substr(2, 6) + Bin8.substr(10, 6) + Bin8.substr(18, 4);
rStr = std::string(1, Bin8ToByte(Bin8.substr(0, 8))) + std::string(1, Bin8ToByte(Bin8.substr(8, 8)));
}
else {
Bin8 = Bin8.substr(2, 6) + Bin8.substr(10, 6) + Bin8.substr(18, 6) + Bin8.substr(26, 6);
rStr = std::string(1, Bin8ToByte(Bin8.substr(0, 8))) + std::string(1, Bin8ToByte(Bin8.substr(8, 8))) + std::string(1, Bin8ToByte(Bin8.substr(16, 8)));
}
return rStr;
}
std::string Base64_Decode(std::string toDecode) {
std::string rStr = "";
for (int i = 0, ni = toDecode.size(); i < ni; i += 4) {
rStr += Decode(toDecode.substr(i, 4));
}
return rStr;
}
调用
Base64_Encode("要加密的串");
Base64_Decode("已经经过Base64Encode的串");
校验
int main(){
std::string f="";
for(int i=1;i<256;++i)f+=char(i);
cout<<f<<endl;
cout<<Base64_Decode(Base64_Encode(f))<<endl;
return 0;
}
//JAVA
public final class Base64 {
final private static byte Base64_Encode_DataSet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".getBytes();
final private static int binValues[]= {-128,64,32,16,8,4,2,1,0};
final private static String getBin8(byte i) {
String str=String.format("%8s", Integer.toBinaryString(i)).replace(' ', '0');
return str.substring(str.length()-8);
}
final private static byte getByte(String Bin8) {
byte rByte = 0;
for(int i=0;i<8;++i)if(Bin8.charAt(i)=='1')rByte+=binValues[i];
return rByte;
}
final private static String Bin8ToBin6(String aStr) {
return "00"+aStr.substring(0, 6)+"00"+aStr.substring(6, 12)+"00"+aStr.substring(12, 18)+"00"+aStr.substring(18, 24);
}
public final static String encode(String toEncode) {
return encode(toEncode.getBytes());
}
public final static String encode(byte[]toEncode) {
String rStr = "";
int i=0,j=1,k=2,ni=toEncode.length,Round3 = ni%3;
String Bin6="";
for (ni=ni/3*3; i < ni; i += 3,j+=3,k+=3) {
Bin6 = Bin8ToBin6(getBin8(toEncode[i])+getBin8(toEncode[j])+getBin8(toEncode[k]));
rStr+= new String( new byte[]{Base64_Encode_DataSet[getByte(Bin6.substring( 0, 8))],Base64_Encode_DataSet[getByte(Bin6.substring( 8, 16))],Base64_Encode_DataSet[getByte(Bin6.substring(16, 24))],Base64_Encode_DataSet[getByte(Bin6.substring(24, 32))]});
}
switch(Round3) {
case 1:
Bin6 = "00"+getBin8(toEncode[i]).substring(0,6)+"00"+getBin8(toEncode[i]).substring(6,8)+"00000100000001000000";
rStr+= new String( new byte[]{Base64_Encode_DataSet[getByte(Bin6.substring( 0, 8))],Base64_Encode_DataSet[getByte(Bin6.substring( 8, 16))],Base64_Encode_DataSet[getByte(Bin6.substring(16, 24))],Base64_Encode_DataSet[getByte(Bin6.substring(24, 32))]});
break;
case 2:
Bin6 = "00"+getBin8(toEncode[i]).substring(0,6)+"00"+getBin8(toEncode[i]).substring(6,8)+getBin8(toEncode[j]).substring(0,4)+"00"+getBin8(toEncode[j]).substring(4,8)+ "0001000000";
rStr+= new String( new byte[]{Base64_Encode_DataSet[getByte(Bin6.substring( 0, 8))],Base64_Encode_DataSet[getByte(Bin6.substring( 8, 16))],Base64_Encode_DataSet[getByte(Bin6.substring(16, 24))],Base64_Encode_DataSet[getByte(Bin6.substring(24, 32))]});
break;
}
return rStr;
}
final private static byte findDict(byte aByte) {
for (byte i=0;i<65;++i)
if(Base64_Encode_DataSet[i]==aByte)
return i;
return -1;
}
public final static byte[] decode(byte[] toDecode) {
return decode(new String(toDecode));
}
public final static byte[] decode(String toDecode) {
int i=0,ni=toDecode.length(),j=0;
byte rByte[]=new byte[toDecode.length()/4*3-(toDecode.charAt(ni-2)=='='?2:toDecode.charAt(ni-1)=='='?1:0)];
String Bin8="";
byte [] aByte;
for (ni-=4; i < ni; i += 4) {
aByte=toDecode.substring(i,i+4).getBytes();
Bin8=getBin8(findDict(aByte[0]))+getBin8(findDict(aByte[1]))+getBin8(findDict(aByte[2]))+getBin8(findDict(aByte[3]));
Bin8=Bin8.substring(2,8)+Bin8.substring(10,16)+Bin8.substring(18,24)+Bin8.substring(26,32);
rByte[j++]=getByte(Bin8.substring(0,8));
rByte[j++]=getByte(Bin8.substring(8,16));
rByte[j++]=getByte(Bin8.substring(16,24));
}
aByte=toDecode.substring(i,i+4).getBytes();
Bin8=getBin8(findDict(aByte[0]))+getBin8(findDict(aByte[1]))+getBin8(findDict(aByte[2]))+getBin8(findDict(aByte[3]));
if(Bin8.charAt(17)=='1'){
rByte[j++]=getByte(Bin8.substring(2,8)+Bin8.substring(10,12));
}
else if(Bin8.charAt(25)=='1'){
Bin8=Bin8.substring(2,8)+Bin8.substring(10,16)+Bin8.substring(18,22);
rByte[j++]=getByte(Bin8.substring(0,8));
rByte[j++]=getByte(Bin8.substring(8,16));
}
else {
Bin8=Bin8.substring(2,8)+Bin8.substring(10,16)+Bin8.substring(18,24)+Bin8.substring(26,32);
rByte[j++]=getByte(Bin8.substring(0,8));
rByte[j++]=getByte(Bin8.substring(8,16));
rByte[j++]=getByte(Bin8.substring(16,24));
}
return rByte;
}
}
//测试 java Base64
byte f[]=new byte[256];
for(int i=0;i<256;++i) f[i]=(byte) i;
byte e[] = java.util.Base64.getEncoder().encode(f);//JDK1.8
byte g[] = Base64.encode(f).getBytes();
System.out.println(java.util.Base64.getEncoder().encodeToString(f));
System.out.println(Base64.encode(f));
System.out.println(Base64.encode(Base64.decode(java.util.Base64.getEncoder().encode(f))));