js 实现 base58加密/解密(包含中文)

作者:neoma安荷

时间:2018年11月1日

来源:CSDN

1. Base58加密原理:和通常base64编码一样,base58编码的作用也是将非可视字符可视化(ASCII化)。但不同的是base58编码去掉了几个看起来会产生歧义的字符,如 0 (零), O (大写字母O), I (大写的字母i) and l (小写的字母L) ,和几个影响双击选择的字符,如/, +。结果字符集正好58个字符(包括9个数字,24个大写字母,25个小写字母)。

转载者注:由于IE8及以下版本不支持Map对象,需要换成Chrome浏览器,或者参考下面文章,重写了Map对象。

http://btc.mom/8502/

 

2. 直接上代码(加密):

a 先存ALPHABET_MAP(方便后期检查当前是否为Base58编码)

  1. var ALPHABET = ‘123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz’;
  2. var ALPHABET_MAP = {};
  3. var BASE = 58;
  4. for (var i = 0; i < ALPHABET.length; i++) {
  5.   ALPHABET_MAP[ALPHABET.charAt(i)] = i;
  6. }
  7. // 得到对象ALPHABET_MAP —> {1: 0, 2: 1, 3: 2, 4: 3, 5: 4, 6: 5, 7: 6, 8: 7, 9: 8, A: 9, B: 10, C: 11, D: 12, E: 13, …, y: 56, z: 57}

 

b 将字符串转为byte字节数组(这里用的UTF8)

  1. // 字符串转utf8格式的字节数组(英文和数字直接返回的acsii码,中文转%xx之后打断当成16进制转10进制)
  2. function ToUTF8(str) {
  3.     var result = new Array();
  4.     var k = 0;
  5.     for (var i = 0; i < str.length; i++) {
  6.         var j = encodeURI(str[i]);
  7.         if (j.length==1) {
  8.             // 未转换的字符
  9.             result[k++] = j.charCodeAt(0);
  10.         } else {
  11.             // 转换成%XX形式的字符
  12.             var bytes = j.split(“%”);
  13.             for (var l = 1; l < bytes.length; l++) {
  14.                 result[k++] = parseInt(“0x” + bytes[l]);
  15.             }
  16.         }
  17.     }
  18.     return result;
  19. }
  20. // 如果有特殊需求,要转成utf16,可以用以下函数
  21. function ToUTF16(str) {
  22.     var result = new Array();
  23.     var k = 0;
  24.     for (var i = 0; i < str.length; i++) {
  25.         var j = str[i].charCodeAt(0);
  26.         result[k++] = j & 0xFF;
  27.         result[k++] = j >> 8;
  28.     }
  29.     return result;
  30. }

 

c Base58加密函数

  1. // 传进已经转成字节的数组 –>buffer(utf8格式)
  2. function encode(buffer) {
  3.  if (buffer.length === 0) return ”;
  4.  var i,
  5.   j,
  6.   digits = [0];
  7.  for (i = 0; i < buffer.length; i++) {
  8.   for (j = 0; j < digits.length; j++){
  9.             // 将数据转为二进制,再位运算右边添8个0,得到的数转二进制
  10.             // 位运算–>相当于 digits[j].toString(2);parseInt(10011100000000,2)
  11.             digits[j] <<= 8;
  12.         }
  13.   digits[0] += buffer[i];
  14.   var carry = 0;
  15.   for (j = 0; j < digits.length; ++j) {
  16.    digits[j] += carry;
  17.    carry = (digits[j] / BASE) | 0;
  18.    digits[j] %= BASE;
  19.   }
  20.   while (carry) {
  21.    digits.push(carry % BASE);
  22.    carry = (carry / BASE) | 0;
  23.   }
  24.  }
  25.  // deal with leading zeros
  26.  for (i = 0; buffer[i] === 0 && i < buffer.length – 1; i++) digits.push(0);
  27.  return digits
  28.   .reverse()
  29.   .map(function(digit) {
  30.    return ALPHABET[digit];
  31.   })
  32.   .join(”);
  33. }
  34. // ToUTF8(‘6嘎’) —>[54, 229, 152, 142]
  35. // encode(ToUTF8(‘6嘎’)) —> 2QPT7B
  36. console.log(encode(ToUTF8(‘6嘎’)))

 

3 直接上代码(解密):

a 解密成字节数组

  1. // string —> 加密后的字符串
  2. function decode(string) {
  3. if (string.length === 0) return [];
  4. var i,
  5. j,
  6. bytes = [0];
  7. for (i = 0; i < string.length; i++) {
  8. var c = string[i];
  9. // c是不是ALPHABET_MAP的key
  10. if (!(c in ALPHABET_MAP)) throw new Error(‘Non-base58 character’);
  11. for (j = 0; j < bytes.length; j++) bytes[j] *= BASE;
  12. bytes[0] += ALPHABET_MAP[c];
  13. var carry = 0;
  14. for (j = 0; j < bytes.length; ++j) {
  15. bytes[j] += carry;
  16. carry = bytes[j] >> 8;
  17. // 0xff –> 11111111
  18. bytes[j] &= 0xff;
  19. }
  20. while (carry) {
  21. bytes.push(carry & 0xff);
  22. carry >>= 8;
  23. }
  24. }
  25. // deal with leading zeros
  26. for (i = 0; string[i] === ‘1’ && i < string.length – 1; i++) bytes.push(0);
  27. return bytes.reverse();
  28. }
  29. // [54, 229, 152, 142]
  30. console.log(decode(2QPT7B))

 

b 将字节数组解密成字符串

  1. // 传字节数组
  2. function byteToString(arr) {
  3. if (typeof arr === ‘string’) {
  4. return arr;
  5. }
  6. var str = ”,
  7. _arr = arr;
  8. for (var i = 0; i < _arr.length; i++) {
  9. // 数组中每个数字转为二进制 匹配出开头为1的直到0的字符
  10. // eg:123–>”1111011″–>{0:”1111″,groups: undefined, index: 0, input: “1111011”}
  11. var one = _arr[i].toString(2),
  12. v = one.match(/^1+?(?=0)/);
  13. if (v && one.length == 8) {
  14. var bytesLength = v[0].length;
  15. var store = _arr[i].toString(2).slice(7 – bytesLength);
  16. for (var st = 1; st < bytesLength; st++) {
  17. store += _arr[st + i].toString(2).slice(2);
  18. }
  19. str += String.fromCharCode(parseInt(store, 2));
  20. i += bytesLength – 1;
  21. } else {
  22. str += String.fromCharCode(_arr[i]);
  23. }
  24. }
  25. return str;
  26. }
  27. // 6嘎
  28. console.log([54, 229, 152, 142])

相关文章:

发表评论