用JS进行Base64编码 解码(base62x在线解码)

2023-03-04 4:54:48 密语知识 思思

  从IE10+浏览器开始,所有浏览器就原生提供了Base64编码、解码方法,不仅可以用于浏览器环境,Service Worker环境也可以使用。

方法名就是 atob 和 btoa ,具体语法如下:

IE8/IE9的polyfill

  当下,仍有不少PC项目还需要兼容IE9,所以,我们可以专门针对这些浏览器再引入一段ployfill脚本或者一个JS文件即可。

[if IE] 表示所有IE浏览器,由于IE10+浏览器已经放弃了著名的IE条件注释的支持,Chrome等浏览器本身就不支持这个IE私有语法,因此,很天然的,上面一段script引入只在IE9-浏览器下有效。而我们本来就希望只IE8,IE9浏览器引入ployfill,于是正好完美衔接上。

也就是原生支持atob和btoa方法的浏览器认为就是一段无需关心的HTML注释,不支持atob和btoa的IE9及其以下浏览器则会加载我们的base64-polyfill.js,使浏览器也支持 window.btoa 和 window.atob 这个语法。

开源的 base64.js ,使用很简单,浏览器引入该JS文件,然后Base64编码这样:

解码就调用 decode 方法,如下:

什么是BASE64编码?

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在发送电子邮件时,服务器认证的用户名和密码需要用Base64编码,附件也需要用Base64编码。

下面简单介绍Base64算法的原理,由于代码太长就不在此贴出

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:

0 A 17 R 34 i 51 z

1 B 18 S 35 j 52 0

2 C 19 T 36 k 53 1

3 D 20 U 37 l 54 2

4 E 21 V 38 m 55 3

5 F 22 W 39 n 56 4

6 G 23 X 40 o 57 5

7 H 24 Y 41 p 58 6

8 I 25 Z 42 q 59 7

9 J 26 a 43 r 60 8

10 K 27 b 44 s 61 9

11 L 28 c 45 t 62 +

12 M 29 d 46 u 63 /

13 N 30 e 47 v

14 O 31 f 48 w (pad) =

15 P 32 g 49 x

16 Q 33 h 50 y

原文的字节最后不够3个的地方用0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。

举一个例子,abc经过Base64编码以后的结果是YWJj.

发邮件的时候所写的信息自动在后台转换然后传输...

参考资料:

base64解码,不能解出中文怎么回事?能不能给个代码。。谢谢

string str = "张利峰";

string encodestr = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(str));

string decodestr = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(encodestr));

求进行base64解码的思路

关于这个编码的规则:

①.把3个字符变成4个字符..

②每76个字符加一个换行符..

③.最后的结束符也要处理..

对于①就是 4个字符32位..有个字符..24位...相差8个位..这8个位..会平均分给每个字节的高两位..则好2*4 = 8.吗...

下面是我用C++实现的...带有注释...通过移位操作实现的...对移位操作不熟悉的朋友可能有点吃力了...

void base642(char * string ,char * pch)

{

int i = 0;

BYTE b1 ,b2 ,b3;

CAtlStringA str(string);

int len = str.GetLength();

char b;

do

{

//

b1 = string[i++];

//b1 右移2位..高2位清0...

//b1.剩下2位要放在第2个字符中..

b = BASE64TABLE[b12];

//得到第1个字符..

*pch ++ = b;

//判断是不是该换行了..76个字符要换行.放在这里..避免i=1的时候换行..

if(i % 76 == 0)

{

*pch ++ = '\r';

*pch ++ = '\n';

}

b2 = string[i++];

//(b1的最后2位要放在b2的第6位(7.8两位要填充0))b1.要左移4位... b2 右移4位...然后相加..在把最高2位清0..

//b2.剩下4位.要放在第3个字符中...

b = BASE64TABLE[((b1 4) + (b2 4)) (0x3f)];

//得到第2个字符..

*pch ++ = b;

//如果没有第3个字符了..那就停止循环了..

////这里不能是= ...因为还要处理最后一个0x00结束符..len不包含最后结束符...

if(i len)

break;//①

b3 = (BYTE) string[i++];

//b2的4位要放在第3个字符的第6位...b2.要左移2位...b3要右移6位..高2位放在此字符的最后两位..

//b3 就剩下了6个字符...

b = BASE64TABLE[((b2 2) + (b3 6)) (0x3f)];

*pch ++ = b;

//如果超过了.就停止了吧..

if(i len)

break;//②

///b3高2位清0 .就可以得到第4个字符...

b = BASE64TABLE[b3 (0x3f)];

*pch ++ = b;

}while(i len);

//取得余数..

int residue = len % 3;

///判断最后要加几个=号..

int y = (residue == 1) ? 2 : (residue == 2 ? 1 : 0) ;

for(int i = 0;i y ;i++)

*pch++ = '=';

/*

这个算法...当中的break.总是感觉会丢失位...

但是仔细一想.最后一字符是0x00....丢失了..也不要紧..

假设有1个字符.. 加上一个结束符..实际上是两个字符..到①这个位置会break...丢失了4位...这4位全部是0..

假设有2个字符..加上一个结束符..实际上是三个字符.到②这个位置会break..丢失6位..同伴全部是0..

假设有3个字符...刚好处理完毕...最后一个结束符..不会处理了...

*/

}

void base642(char * string ,char * pch)

{

int i = 0;

BYTE b1 ,b2 ,b3;

CAtlStringA str(string);

int len = str.GetLength();

char b;

do

{

//

b1 = string[i++];

//b1 右移2位..高2位清0...

//b1.剩下2位要放在第2个字符中..

b = BASE64TABLE[b12];

//得到第1个字符..

*pch ++ = b;

//判断是不是该换行了..76个字符要换行.放在这里..避免i=1的时候换行..

if(i % 76 == 0)

{

*pch ++ = '\r';

*pch ++ = '\n';

}

b2 = string[i++];

//(b1的最后2位要放在b2的第6位(7.8两位要填充0))b1.要左移4位... b2 右移4位...然后相加..在把最高2位清0..

//b2.剩下4位.要放在第3个字符中...

b = BASE64TABLE[((b1 4) + (b2 4)) (0x3f)];

//得到第2个字符..

*pch ++ = b;

//如果没有第3个字符了..那就停止循环了..

////这里不能是= ...因为还要处理最后一个0x00结束符..len不包含最后结束符...

if(i len)

break;//①

b3 = (BYTE) string[i++];

//b2的4位要放在第3个字符的第6位...b2.要左移2位...b3要右移6位..高2位放在此字符的最后两位..

//b3 就剩下了6个字符...

b = BASE64TABLE[((b2 2) + (b3 6)) (0x3f)];

*pch ++ = b;

//如果超过了.就停止了吧..

if(i len)

break;//②

///b3高2位清0 .就可以得到第4个字符...

b = BASE64TABLE[b3 (0x3f)];

*pch ++ = b;

}while(i len);

//取得余数..

int residue = len % 3;

///判断最后要加几个=号..

int y = (residue == 1) ? 2 : (residue == 2 ? 1 : 0) ;

for(int i = 0;i y ;i++)

*pch++ = '=';

/*

这个算法...当中的break.总是感觉会丢失位...

但是仔细一想.最后一字符是0x00....丢失了..也不要紧..

假设有1个字符.. 加上一个结束符..实际上是两个字符..到①这个位置会break...丢失了4位...这4位全部是0..

假设有2个字符..加上一个结束符..实际上是三个字符.到②这个位置会break..丢失6位..同伴全部是0..

假设有3个字符...刚好处理完毕...最后一个结束符..不会处理了...

*/

}

这个是解码的函数.

view plaincopy to clipboardprint?

void base644(char * string ,char * pch)

{

CAtlStringA tab("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");

CAtlStringA str(string);

str.Remove('=');

str.Remove('\r');

str.Remove('\n');

int len = str.GetLength();

int i = 0;

BYTE b1 ,b2 ,b3 ,b4;

char ch;

do

{

//找字符1的位置.

b1 = tab.Find((str[i++]));

//找字符2的位置.

b2 = tab.Find((str[i++]));

//b1左移两位..还原.此时少了最后两位...b2的第6位和第5位..要右移4位(变成最后两位.)..此时和b1相加...即可

//b1还原...

ch = (b1 2) + (b2 4);

//得到此字节..

*pch ++ = ch;

//超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..

if(i = len)

break;

//取第3个字符..的位置

b3 = tab.Find((str[i++]));

//从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..

//还原第2个字符...b2中有b1的两个位..所以b2左移4位..即可把b1的两个位和00两个最高位去除..b2中只有

//有效的4个位..b3中还有4个位....b3右移2位..即可把5位6位变成低4位..因为要相加的..

ch = (b2 4) + (b3 2);

*pch ++ = ch;

//超过了..break吧.

if(i = len)

break;

//找第4个字符..

b4 = tab.Find((str[i++]));

//还原第3个字符...b3中有两个位...要放在最高两位...所以左移6位..加上b4即可..(b4的高两位为0..)

ch = (b3 6) + b4;

*pch ++ = ch;

}

while(i len);

////最后加个结束符...

*pch =0x00;

}

void base644(char * string ,char * pch)

{

CAtlStringA tab("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");

CAtlStringA str(string);

str.Remove('=');

str.Remove('\r');

str.Remove('\n');

int len = str.GetLength();

int i = 0;

BYTE b1 ,b2 ,b3 ,b4;

char ch;

do

{

//找字符1的位置.

b1 = tab.Find((str[i++]));

//找字符2的位置.

b2 = tab.Find((str[i++]));

//b1左移两位..还原.此时少了最后两位...b2的第6位和第5位..要右移4位(变成最后两位.)..此时和b1相加...即可

//b1还原...

ch = (b1 2) + (b2 4);

//得到此字节..

*pch ++ = ch;

//超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..

if(i = len)

break;

//取第3个字符..的位置

b3 = tab.Find((str[i++]));

//从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..

//还原第2个字符...b2中有b1的两个位..所以b2左移4位..即可把b1的两个位和00两个最高位去除..b2中只有

//有效的4个位..b3中还有4个位....b3右移2位..即可把5位6位变成低4位..因为要相加的..

ch = (b2 4) + (b3 2);

*pch ++ = ch;

//超过了..break吧.

if(i = len)

break;

//找第4个字符..

b4 = tab.Find((str[i++]));

//还原第3个字符...b3中有两个位...要放在最高两位...所以左移6位..加上b4即可..(b4的高两位为0..)

ch = (b3 6) + b4;

*pch ++ = ch;

}

while(i len);

////最后加个结束符...

*pch =0x00;

}

//下面是测试程序.

view plaincopy to clipboardprint?

int _tmain(int argc, _TCHAR* argv[])

{

char pch[0x1dc]={0};

CAtlStringA str("谢谢你啊" );

CStrBufA buf(str);

base642(CStrBufA::PXSTR(buf),pch);

cout pchendl;

cout "********************************************************************************"endl;

CAtlStringA str2 = "0LvQu8TjsKE=";

CStrBufA buf2(str2);

RtlZeroMemory(pch ,0x1dc);

base644(CStrBufA::PXSTR(buf2) ,pch);

cout pchendl;

return 0;

}

int _tmain(int argc, _TCHAR* argv[])

{

char pch[0x1dc]={0};

CAtlStringA str("谢谢你啊" );

CStrBufA buf(str);

base642(CStrBufA::PXSTR(buf),pch);

cout pchendl;

cout "********************************************************************************"endl;

CAtlStringA str2 = "0LvQu8TjsKE=";

CStrBufA buf2(str2);

RtlZeroMemory(pch ,0x1dc);

base644(CStrBufA::PXSTR(buf2) ,pch);

cout pchendl;

return 0;

}

用到的数组.

const char BASE64TABLE[64]={

'A','B','C','D','E','F','G','H','I','J','K','L','M','N',

'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b',

'c','d','e','f','g','h','i','j','k','l','m','n','o','p',

'q','r','s','t','u','v','w','x','y','z','0','1','2','3',

'4','5','6','7','8','9','+','/'

};

这个作用就是....26刚好64...base64会计算每个字符的6位...然后从这个表中选中一个字母.作为最后的编码...base64当中没有其它的字符了...

如果字符数不是3的倍数..就相应的加上=号..最多有两个等号了..纯粹是为了凑数...

上面是C的,下面是C++的:

#include string

using namespace std;

class ZBase64

{

public:

/*编码

DataByte

[in]输入的数据长度,以字节为单位

*/

string Encode(const unsigned char* Data,int DataByte);

/*解码

DataByte

[in]输入的数据长度,以字节为单位

OutByte

[out]输出的数据长度,以字节为单位,请不要通过返回值计算

输出数据的长度

*/

string Decode(const char* Data,int DataByte,int OutByte);

};

#include "stdAfx.h"

#include "ZBase64.h"

string ZBase64::Encode(const unsigned char* Data,int DataByte)

{

//编码表

const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

//返回值

string strEncode;

unsigned char Tmp[4]={0};

int LineLength=0;

for(int i=0;i(int)(DataByte / 3);i++)

{

Tmp[1] = *Data++;

Tmp[2] = *Data++;

Tmp[3] = *Data++;

strEncode+= EncodeTable[Tmp[1] 2];

strEncode+= EncodeTable[((Tmp[1] 4) | (Tmp[2] 4)) 0x3F];

strEncode+= EncodeTable[((Tmp[2] 2) | (Tmp[3] 6)) 0x3F];

strEncode+= EncodeTable[Tmp[3] 0x3F];

if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}

}

//对剩余数据进行编码

int Mod=DataByte % 3;

if(Mod==1)

{

Tmp[1] = *Data++;

strEncode+= EncodeTable[(Tmp[1] 0xFC) 2];

strEncode+= EncodeTable[((Tmp[1] 0x03) 4)];

strEncode+= "==";

}

else if(Mod==2)

{

Tmp[1] = *Data++;

Tmp[2] = *Data++;

strEncode+= EncodeTable[(Tmp[1] 0xFC) 2];

strEncode+= EncodeTable[((Tmp[1] 0x03) 4) | ((Tmp[2] 0xF0) 4)];

strEncode+= EncodeTable[((Tmp[2] 0x0F) 2)];

strEncode+= "=";

}

return strEncode;

}

string ZBase64::Decode(const char* Data,int DataByte,int OutByte)

{

//解码表

const char DecodeTable[] =

{

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

62, // '+'

0, 0, 0,

63, // '/'

52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'

0, 0, 0, 0, 0, 0, 0,

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,

13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'

0, 0, 0, 0, 0, 0,

26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,

39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'

};

//返回值

string strDecode;

int nValue;

int i= 0;

while (i DataByte)

{

if (*Data != '\r' *Data!='\n')

{

nValue = DecodeTable[*Data++] 18;

nValue += DecodeTable[*Data++] 12;

strDecode+=(nValue 0x00FF0000) 16;

OutByte++;

if (*Data != '=')

{

nValue += DecodeTable[*Data++] 6;

strDecode+=(nValue 0x0000FF00) 8;

OutByte++;

if (*Data != '=')

{

nValue += DecodeTable[*Data++];

strDecode+=nValue 0x000000FF;

OutByte++;

}

}

i += 4;

}

else// 回车换行,跳过

{

Data++;

i++;

}

}

return strDecode;

}

使用示例(结合CxImage库):

CString CScanDlg::EncodeImage()

{//对图片进行Base64编码

ZBase64 zBase;

//图片编码

CxImage image; // 定义一个CxImage对象

image.Load(this-m_strImgPath, CXIMAGE_FORMAT_JPG); //先装载jpg文件,需要指定文件类型

long size=0;//得到图像大小

BYTE* buffer=0;//存储图像数据的缓冲

image.Encode(buffer,size,CXIMAGE_FORMAT_JPG);//把image对象中的图像以type类型数据copy到buffer

string strTmpResult=zBase.Encode(buffer,size);

CString result;

result = strTmpResult.c_str();

return result;

}

void CScanDlg::DecodeImageData(CString strData)

{//对Base64编码过的数据解码并显示原图片

ZBase64 zBase;

int OutByte=0;

string strTmpResult=zBase.Decode(strData,strData.GetLength(),OutByte);

int i,len = strTmpResult.length();

BYTE *buffer = new BYTE[len];

for (i=0;ilen;++i)

{

buffer[i] = strTmpResult[i];

}

CxImage image(buffer,len,CXIMAGE_FORMAT_JPG);//把内存缓冲buffer中的数据构造成Image对象

delete [] buffer;

CDC* hdc = m_picture.GetDC();

m_bitmap = image.MakeBitmap(hdc-m_hDC);

HBITMAP h0ldBmp = m_picture.SetBitmap(m_bitmap);

if(h0ldBmp) DeleteObject(h0ldBmp);

if(hdc-m_hDC) m_picture.ReleaseDC(hdc);

if(m_bitmap) DeleteObject(m_bitmap);

}

关于Base64解码的问题:

你自己调试一下deCode要解密的数据串,这个串的长度应该是4的倍数,否则肯定是会报这个错误的

求采纳