本文主要是介绍记一次手忙脚乱的base64debug之旅,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这几天做了一个需求,读取上传的公私钥,然后利用私钥采用RSA加密摘要,发送给后端。其中运用到了base64
的加解密,RSA加密采用的是node的Crypto
模块,base64
的转码采用的是js-base64, 然而万万没有想到,这里面有坑啊。
(开个玩笑,这个库还是很不错的)
文件的读取
首先是文件的读取,采用的是FileReader
, 并且二进制文件的读取应为readAsArrayBuffer
,否则会乱码。
readFile(file) {return new Promise((resolve, reject) => {const reader = new FileReader();reader.onload = function(evt) {resolve(evt.target.result)};reader.readAsArrayBuffer(file);})
}
从这里读取到的数据,调用Object.prototype.toString.call([data])
,结果为[object Uint8Array]
。
ArrayBuffer
对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer
不能直接操作,而是要通过类型数组对象或DataView
对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
Uint8Array
数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
类型数组对象就是Uint8Array
之类的TypedArray
,我们需要这些对象操作ArrayBuffer
。
这是一个摸索了很久的点,因为有的公私钥读取可以直接采用reader.readAsText(file)
。
ArrayBuffer与base64的转换
另一个摸索了很久的东西便是ArrayBuffer
与base64
的转换,缘由于js-base64
对这两个的转换并不支持。
ArrayBuffer转base64
很令人捉🐔的是,调用库中的方法Base64.encode([ArrayBuffer])
,得出的数据一直不对。
略微看了一下源码。
var _Base64 = global.Base64;
var version = "2.5.1";
// if node.js and NOT React Native, we use Buffer
var buffer;
if (typeof module !== 'undefined' && module.exports) {try {buffer = eval("require('buffer').Buffer");} catch (err) {buffer = undefined;}
}
...
var _encode = buffer ?buffer.from && Uint8Array && buffer.from !== Uint8Array.from? function (u) {return (u.constructor === buffer.constructor ? u : buffer.from(u)).toString('base64')}: function (u) {return (u.constructor === buffer.constructor ? u : new buffer(u)).toString('base64')}: function (u) { return btoa(utob(u)) }
;
var encode = function(u, urisafe) {return !urisafe? _encode(String(u)): _encode(String(u)).replace(/[+\/]/g, function(m0) {return m0 == '+' ? '-' : '_';}).replace(/=/g, '');
};
不知是不是采用IIFE
的关系,buffer
恒为undefined
,并且此时!urisafe
为真,会流入第一个条件,而的u
为Uint8Array
,强制类型转换会导致乱码。
故而不用库,用原生方法。
Buffer.from([key]).toString('base64')
这是ArrayBuffer
转base64
的原生方法。
base64转ArrayBuffer
function _base64ToArrayBuffer(base64) {var binary_string = window.atob(base64);var len = binary_string.length;var bytes = new Uint8Array( len );for (var i = 0; i < len; i++) {bytes[i] = binary_string.charCodeAt(i);}return bytes.buffer;
}
and…
const encryptDigest = crypto.privateEncrypt({ key: privateKey },Buffer.from(_base64ToArrayBuffer(digest))
);
const res = crypto.publicDecrypt({ key: publicKey }, encryptDigest);res.toString('base64') === digest ?
只要用私钥加密的摘要用公钥能成功解密,并且数据不变,就证明这个流程正确了。
其实用window.atob
也可以将ArrayBuffer
转base64
,但是有大小限制,码位应在 0x00 ~ 0xFF 范围内。然而后端小哥说业务不支持ascii
格式的,只能作罢。
javascript – 将base64字符串转换为ArrayBuffer
深入学习 Node.js Buffer
这篇关于记一次手忙脚乱的base64debug之旅的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!