返回顶部
首页 > 资讯 > 前端开发 > node.js >如何分析JavaScrip中的Base64编码和解码
  • 848
分享到

如何分析JavaScrip中的Base64编码和解码

2024-04-02 19:04:59 848人浏览 安东尼
摘要

今天就跟大家聊聊有关如何分析JavaScrip中的Base64编码和解码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Base64是最常用的编码之一

今天就跟大家聊聊有关如何分析JavaScrip中的Base64编码和解码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

Base64是最常用的编码之一,比如开发中用于传递参数、现代浏览器中的<img />标签直接通过Base64字符串来渲染图片以及用于邮件中等等。Base64编码在RFC2045中定义,它被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。

我们知道,任何数据在计算机中都是以二进制的方式存储的。一个字节为8位,一个字符在计算机中存储为一个或多个字节,比如英文字母、数字以及英文标点符号就是用一个 字节来存储的,通常称为ASCII码。而简体中文、繁体中文、日文以及韩文等都是用多字节来存储的,通常称为多字节字符。因为Base64编码是对字符串的编码表示进行处理的,不同编码的字符串的Base64的结果是不同的,所以我们需要了解基本的字符编码知识。

字符编码基础

计算机最开始只支持ASCII码,一个字符用一个字节表示,只用了低7位,***位为0,因此总共有128个ASCII码,范围为0~127。后来为了支持多种地区的语言,各大组织机构和IT厂商开始发明它们自己的编码方案,以便弥补ASCII编码的不足,如GB2312编码、GBK编码和Big5编码等。但这些编码都只是针对局部地区或少数语言文字,没有办法表达所有的语言文字。而且这些不同的编码之间并没有任何联系,它们之间的转换需要通过查表来实现。

为了提高计算机的信息处理和交换功能,使得世界各国的文字都能在计算机中处理,从1984年起,ISO组织就开始研究制定一个全新的标准:通用多八位(即多字节)编码字符集(Universal Multiple-Octet Coded Character Set),简称UCS。标准的编号为:ISO 10646。这一标准为世界各种主要语言的字符(包括简体及繁体的中文字)及附加符号,编制统一的内码。

统一码(Unicode)是Universal Code的缩写,是由另一个叫“Unicode学术学会”(The Unicode Consortium)的机构制定的字符编码系统。Unicode与ISO 10646国际编码标准从内容上来说是同步一致的。具体可参考:Unicode 。

ANSI

ANSI不代表具体的编码,它是指本地编码。比如在简体版windows上它表示GB2312编码,在繁体版windows上它表示Big5编码,在日文操作系统上它表示JIS编码。所以如果您新建了个文本文件并保存为ANSI编码,那么您现在应该知道这个文件的编码为本地编码。

Unicode

Unicode编码是和字符表一一映射的。比如56DE代表汉字'回',这种映射关系是固定不变的。通俗的说Unicode编码就是字符表的坐标,通过56DE就能找到汉字'回'。Unicode编码的实现包括UTF8、UTF16、UTF32等等。

Unicode本身定义的就是每个字符的数值,是字符和自然数的映射关系,而UTF-8或者UTF-16甚至UTF-32则定义了如何在字节流中断字,是计算机领域的概念。

如何分析JavaScrip中的Base64编码和解码

通过上图我们知道,UTF-8编码为变长的编码方式,占1~6个字节,可通过Unicode编码值的区间来判断,并且每个组成UTF8字符的字节都是有规律可循的。本文只讨论UTF8和UTF16这两种编码。

UTF16

UTF16编码使用固定的2个字节来存储。因为是多字节存储,所以它的存储方式分为2种:大端序和小端序。UTF16编码是Unicode最直接的实现方式,通常我们在windows上新建文本文件后保存为Unicode编码,其实就是保存为UTF16编码。UTF16编码在windows上采用小端序的方式存储,以下我新建了个文本文件并保存为Unicode编码来测试,文件中只输入了一个汉字'回',之后我用Editplus打开它,切换到十六进制方式查看,如图所示:

如何分析JavaScrip中的Base64编码和解码

我们看到有4个字节,前2个字节FF FE是文件头,表示这是一个UTF16编码的文件,而DE 56则是'回'的UTF16编码的十六进制。我们经常使用的javascript语言,它内部就是采用UTF16编码,并且它的存储方式为大端序,来看一个例子:

<script type="text/javascript">  console.group('Test Unicode: ');  console.log(('回'.charCodeAt(0)).toString(16).toUpperCase());  </script>

如何分析JavaScrip中的Base64编码和解码

很明显跟刚才Editplus显示的不一样,顺序是相反的,这是因为字节序不一样。具体可参考:UTF-16 。

UTF8

UTF8是采用变长的编码方式,为1~6个字节,但通常我们只把它看作单字节或三字节的实现,因为其它情况实在少见。UTF8编码通过多个字节组合的方式来显示,这是计算机处理UTF8的机制,它是无字节序之分的,并且每个字节都非常有规律,详见上图,在此不再详述。

UTF16和UTF8的相互转换

UTF16转UTF8

UTF16和UTF8之间的相互转换可以通过上图的转换表来实现,判断Unicode码所在的区间就可以得到这个字符是由几个字节所组成,之后通过移位来实现。我们用汉字'回'来举一个转换的例子。

我们已经知道汉字'回'的Unicode码是0x56DE,它介于U+00000800 &ndash; U+0000FFFF之间,所以它是用三个字节来表示的。

如何分析JavaScrip中的Base64编码和解码

所以我们需要将0x56DE这个双字节的值变为三字节的值,注意上图中的x部分,就是对应0x56DE的各位字节,如果您数一下x的个数,会发现刚好是16位。

转换思路

从0x56DE中取出4位放在低位,并和二进制的1110结合,这就是***个字节。从0x56DE中剩下的字节中取出6位放在低位,并和二进制的10结合,这就是第二个字节。第三个字节依照类似的方式实现。

代码实现

为了让大家更好的理解,以下代码只是实现汉字'回'的转换,代码如下:

<script type="text/javascript">    var ucode = 0x56DE;  // 1110xxxx  var byte1 = 0xE0 | ((ucode >> 12) & 0x0F);  // 10xxxxxx  var byte2 = 0x80 | ((ucode >> 6) & 0x3F);  // 10xxxxxx  var byte3 = 0x80 | (ucode & 0x3F);  var utf8 = String.fromCharCode(byte1)          + String.fromCharCode(byte2)          + String.fromCharCode(byte3);   console.group('Test UTF16ToUTF8: ');  console.log(utf8);  console.groupEnd();  </script>

如何分析JavaScrip中的Base64编码和解码

输出的结果看起来像乱码,这是因为JavaScript不知道如何显示UTF8的字符。您或许会说输出不正常转换还有什么用,但您应该知道转换的目的还经常用于传输或api的需要。

UTF8转UTF16

这是UTF16转换到UTF8的逆转换,同样需要对照转换表来实现。还是接上一个例子,我们已经得到了汉字'回'的UTF8编码,这是三个字节的,我们只需要按照转换表来转成双字节的,如图所示,我们需要保留下所有的x。

如何分析JavaScrip中的Base64编码和解码

代码如下:

<script type="text/javascript">    var ucode = 0x56DE;  // 1110xxxx  var byte1 = 0xE0 | ((ucode >> 12) & 0x0F);  // 10xxxxxx  var byte2 = 0x80 | ((ucode >> 6) & 0x3F);  // 10xxxxxx  var byte3 = 0x80 | (ucode & 0x3F);  var utf8 = String.fromCharCode(byte1)          + String.fromCharCode(byte2)          + String.fromCharCode(byte3);   console.group('Test UTF16ToUTF8: ');  console.log(utf8);  console.groupEnd();   // 由三个字节组成,所以分别取出  var c1 = utf8.charCodeAt(0);  var c2 = utf8.charCodeAt(1);  var c3 = utf8.charCodeAt(2);   // 丢弃***个字节的高四位并和第二个字节的高四位组成一个字节  var b1 = (c1 << 4) | ((c2 >> 2) & 0x0F);  // 同理第二个字节和第三个字节组合  var b2 = ((c2 & 0x03) << 6) | (c3 & 0x3F);  // 将b1和b2组成16位  var ucode = ((b1 & 0x00FF) << 8) | b2;  console.group('Test UTF8ToUTF16: ');  console.log(ucode.toString(16).toUpperCase(), String.fromCharCode(ucode));  console.groupEnd();  </script>

如何分析JavaScrip中的Base64编码和解码

知道了转换规则,就很容易实现了。

Base64编码

Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。由于2的6次方为64,所以每6个位为一个单元,对应某个可打印字符。当原数据不是3的整数倍时,如果***剩下两个输入数据,在编码结果后加1个“=;如果***剩下一个输入数据,编码结果后加2个“=;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

转码对照表

每6个单元高位补2个零形成的字节位于0~63之间,通过在转码表中查找对应的可打印字符。“=”用于填充。如下图所示为转码表。

如何分析JavaScrip中的Base64编码和解码

具体可参考: Base64 。

Base64解码

解码是编码的逆过程,先看后面补了几个“=”号,最多只可能补2个“=”号。一个“=”相当于补了2个0,所以去掉后面补的0后,再按8位展开,即可还原。

JavaScript实现Base64的编码和解码

之前已经详细讲解了整个过程,本文的例子都是采用UTF8编码的字符串作为Base64编码的基础。因为JavaScript内部是使用Unicode编码,所以需要有个转换过程,原理之前也详细讲解过并给出了示例,以下是代码实现:

<script type="text/javascript">   var Base64 = {      // 转码表      table : [              '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', '+', '/'     ],      UTF16ToUTF8 : function(str) {          var res = [], len = str.length;          for (var i = 0; i < len; i++) {              var code = str.charCodeAt(i);              if (code > 0x0000 && code <= 0x007F) {                  // 单字节,这里并不考虑0x0000,因为它是空字节                  // U+00000000 &ndash; U+0000007F  0xxxxxxx                  res.push(str.charAt(i));              } else if (code >= 0x0080 && code <= 0x07FF) {                  // 双字节                  // U+00000080 &ndash; U+000007FF  110xxxxx 10xxxxxx                  // 110xxxxx                  var byte1 = 0xC0 | ((code >> 6) & 0x1F);                  // 10xxxxxx                  var byte2 = 0x80 | (code & 0x3F);                  res.push(                      String.fromCharCode(byte1),                       String.fromCharCode(byte2)                  );              } else if (code >= 0x0800 && code <= 0xFFFF) {                  // 三字节                  // U+00000800 &ndash; U+0000FFFF  1110xxxx 10xxxxxx 10xxxxxx                  // 1110xxxx                  var byte1 = 0xE0 | ((code >> 12) & 0x0F);                  // 10xxxxxx                  var byte2 = 0x80 | ((code >> 6) & 0x3F);                  // 10xxxxxx                  var byte3 = 0x80 | (code & 0x3F);                  res.push(                      String.fromCharCode(byte1),                       String.fromCharCode(byte2),                       String.fromCharCode(byte3)                  );              } else if (code >= 0x00010000 && code <= 0x001FFFFF) {                  // 四字节                  // U+00010000 &ndash; U+001FFFFF  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx              } else if (code >= 0x00200000 && code <= 0x03FFFFFF) {                  // 五字节                  // U+00200000 &ndash; U+03FFFFFF  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx              } else  {                  // 六字节                  // U+04000000 &ndash; U+7FFFFFFF  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx              }          }           return res.join('');      },      UTF8ToUTF16 : function(str) {          var res = [], len = str.length;          var i = 0;          for (var i = 0; i < len; i++) {              var code = str.charCodeAt(i);              // 对***个字节进行判断              if (((code >> 7) & 0xFF) == 0x0) {                  // 单字节                  // 0xxxxxxx                  res.push(str.charAt(i));              } else if (((code >> 5) & 0xFF) == 0x6) {                  // 双字节                  // 110xxxxx 10xxxxxx                  var code2 = str.charCodeAt(++i);                  var byte1 = (code & 0x1F) << 6;                  var byte2 = code2 & 0x3F;                  var utf16 = byte1 | byte2;                  res.push(Sting.fromCharCode(utf16));              } else if (((code >> 4) & 0xFF) == 0xE) {                  // 三字节                  // 1110xxxx 10xxxxxx 10xxxxxx                  var code2 = str.charCodeAt(++i);                  var code3 = str.charCodeAt(++i);                  var byte1 = (code << 4) | ((code2 >> 2) & 0x0F);                  var byte2 = ((code2 & 0x03) << 6) | (code3 & 0x3F);                  utf16 = ((byte1 & 0x00FF) << 8) | byte2                  res.push(String.fromCharCode(utf16));              } else if (((code >> 3) & 0xFF) == 0x1E) {                  // 四字节                  // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx              } else if (((code >> 2) & 0xFF) == 0x3E) {                  // 五字节                  // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx              } else  {                  // 六字节                  // 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx              }          }           return res.join('');      },      encode : function(str) {          if (!str) {              return '';          }          var utf8    = this.UTF16ToUTF8(str); // 转成UTF8          var i = 0; // 遍历索引          var len = utf8.length;          var res = [];          while (i < len) {              var c1 = utf8.charCodeAt(i++) & 0xFF;              res.push(this.table[c1 >> 2]);              // 需要补2个=              if (i == len) {                  res.push(this.table[(c1 & 0x3) << 4]);                  res.push('==');                  break;              }              var c2 = utf8.charCodeAt(i++);              // 需要补1个=              if (i == len) {                  res.push(this.table[((c1 & 0x3) << 4) | ((c2 >> 4) & 0x0F)]);                  res.push(this.table[(c2 & 0x0F) << 2]);                  res.push('=');                  break;              }              var c3 = utf8.charCodeAt(i++);              res.push(this.table[((c1 & 0x3) << 4) | ((c2 >> 4) & 0x0F)]);              res.push(this.table[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)]);              res.push(this.table[c3 & 0x3F]);          }           return res.join('');      },      decode : function(str) {          if (!str) {              return '';          }           var len = str.length;          var i   = 0;          var res = [];           while (i < len) {              code1 = this.table.indexOf(str.charAt(i++));              code2 = this.table.indexOf(str.charAt(i++));              code3 = this.table.indexOf(str.charAt(i++));              code4 = this.table.indexOf(str.charAt(i++));               c1 = (code1 << 2) | (code2 >> 4);              c2 = ((code2 & 0xF) << 4) | (code3 >> 2);              c3 = ((code3 & 0x3) << 6) | code4;               res.push(String.fromCharCode(c1));               if (code3 != 64) {                  res.push(String.fromCharCode(c2));              }              if (code4 != 64) {                  res.push(String.fromCharCode(c3));              }           }           return this.UTF8ToUTF16(res.join(''));      }  };   console.group('Test Base64: ');  var b64 = Base64.encode('Hello, oschina!又是一年春来到~');  console.log(b64);  console.log(Base64.decode(b64));  console.groupEnd();  </script>

如何分析JavaScrip中的Base64编码和解码

不得不说,在JavaScript中实现确实很麻烦。我们来看下PHP对同样的字符串编码的结果:

如何分析JavaScrip中的Base64编码和解码

因为字符编码是一样的,所以结果也一样。

看完上述内容,你们对如何分析JavaScrip中的Base64编码和解码有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网node.js频道,感谢大家的支持。

--结束END--

本文标题: 如何分析JavaScrip中的Base64编码和解码

本文链接: https://lsjlt.com/news/86239.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何分析JavaScrip中的Base64编码和解码
    今天就跟大家聊聊有关如何分析JavaScrip中的Base64编码和解码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Base64是最常用的编码之一...
    99+
    2024-04-02
  • JS Base64编码解码的示例分析
    这篇文章主要介绍JS Base64编码解码的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 基础不牢,选型糟糕糟糕的技术选型往往源自自身技术广度不足。就在数月前,一个前端...
    99+
    2024-04-02
  • Vue中如何使用base64编码和解码
    目录Vue使用base64编码和解码Vue路由获取query中base64解码出错总结Vue使用base64编码和解码 在项目根目录下安装 npm install --save js...
    99+
    2023-02-08
    Vue使用base64编码 Vue使用base64解码 base64编码和解码
  • php如何实现Base64的编码和解码
    这篇文章主要讲解了“php如何实现Base64的编码和解码”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php如何实现Base64的编码和解码”吧!PHP内置函数的使用PHP中提供了两个内置...
    99+
    2023-07-05
  • mysql中Base64编码与解码
    在mysql中,有些数据我们不想让别人直观的看到,这时可以使用Base编码与解码。 MySQL在5.6版本的时候增加了to_base64和from_base64函数,在此之前没有内部函数, 用法举例:  1、to_base64  编...
    99+
    2019-10-07
    mysql中Base64编码与解码
  • CSS中图片Base64编码的示例分析
    这篇文章主要介绍了CSS中图片Base64编码的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是 base64 编码  我不是来讲概念的,直接切入正题,图片的 b...
    99+
    2023-06-15
  • base64编码原理的示例分析
    这篇文章将为大家详细讲解有关base64编码原理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 base64编码原理 最近在做将文件转成base64编码,并...
    99+
    2024-04-02
  • python密码学Base64编码和解码的方法
    本文小编为大家详细介绍“python密码学Base64编码和解码的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“python密码学Base64编码和解码的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。B...
    99+
    2023-06-30
  • 了解MySQL中的base64编码?
    要对 Base64 进行编码,您可以使用两个功能 -TO_BASE64()FROM_BASE64()base64 编码的语法如下 -SELECT TO_BASE64(anyValue) as AnyVariableName;base...
    99+
    2023-10-22
  • JS如何在浏览器中解析Base64编码图像
    这篇文章主要介绍JS如何在浏览器中解析Base64编码图像,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!浏览器对Base64的支持 图像是最经常被使用的一种二进制文件。而现代的浏览器...
    99+
    2024-04-02
  • 如何解决PHP base64编码后解码乱码的问题
    如何解决PHP base64编码后解码乱码的问题 PHP base64编码后解码乱码的解决办法:用GET形式传递时,防止【+】号被替换成空格即可,代码为【$str = base64_decode(str_replace(" ","...
    99+
    2023-09-06
    servlet java html
  • python密码学Base64编码和解码教程
    目录Base64编码编码程序输出解码程序输出差异在ASCII和base64之间缺点Base64编码 Base64编码将二进制数据转换为文本格式,通过通信通道传递,用户可以安全地处理文...
    99+
    2024-04-02
  • php怎么实现Base64的编码和解码
    Base64算法是一种将二进制数据转换为ASCII字符的编码方式,使得数据可以在传输过程中不被修改或损坏,同时也可以隐藏数据的真实内容。在PHP中,可以利用内置函数或手动编写代码实现Base64的编码和解码。PHP内置函数的使用PHP中提供...
    99+
    2023-05-14
    Base64 php
  • Java Base64编码方法详解及实例分析
    Base64.encodeBase64String方法是一个Java语言中用于Base64编码的方法。它可以将二进制数据转换为Base64编码的字符串形式。在本文中,我们将详细解释这个方法的使用,提供完整的实例和代码,并分析运行结果。最后,...
    99+
    2023-09-04
    java 开发语言
  • Java中的base64编码器
    简介 什么是Base64编码呢?在回答这个问题之前,我们需要了解一下计算机中文件的分类,对于计算机来说文件可以分为两类,一类是文本文件,一类是二进制文件。 对于二进制文件来说,其内容...
    99+
    2024-04-02
  • JavaScript、C#中URL编码和解码的示例分析
    这篇文章主要为大家展示了“JavaScript、C#中URL编码和解码的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript、C#中URL...
    99+
    2024-04-02
  • Python如何实现base64编码
    这篇“Python如何实现base64编码”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python如何实现base64编码...
    99+
    2023-06-30
  • Python简单实现Base64编码和解码的方法
    本文实例讲述了Python简单实现Base64编码和解码的方法。分享给大家供大家参考,具体如下: Base64编码是一种“防君子不防小人”的编码方式。广泛应用于MIME协议,作为电子邮件的传输编码,生成的编...
    99+
    2022-06-04
    简单 方法 Python
  • 关于base64编码和解码的js工具函数
    目录base64编码和解码的js工具函数前端实现base64解码编码方法一:btoa 和 atob方法二:下包方法三:js实现总结base64编码和解码的js工具函数 上代码 // ...
    99+
    2023-02-08
    关于base64编码 关于base64解码 js工具函数
  • java base64编码、解码的三种方式
    在Java中,可以使用以下三种方式进行base64编码和解码:1. 使用Java8的java.util.Base64类(推荐)```...
    99+
    2023-08-24
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作