/*! * base58.js - base58 for bcoin * Copyright (c) 2014-2015, Fedor Indutny (MIT License) * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; /** * @module utils/base58 */ const assert = require('assert'); const native = require('../native').binding; /* * Base58 */ const base58 = '' + '123456789' + 'ABCDEFGHJKLMNPQRSTUVWXYZ' + 'abcdefghijkmnopqrstuvwxyz'; const unbase58 = {}; for (let i = 0; i < base58.length; i++) unbase58[base58[i]] = i; /** * Encode a base58 string. * @see https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp * @param {Buffer} data * @returns {Base58String} */ exports.encode = function encode(data) { assert(Buffer.isBuffer(data)); let zeroes = 0; let i = 0; for (; i < data.length; i++) { if (data[i] !== 0) break; zeroes++; } const b58 = Buffer.allocUnsafe(((data.length * 138 / 100) | 0) + 1); b58.fill(0); let length = 0; for (; i < data.length; i++) { let carry = data[i]; let j = 0; for (let k = b58.length - 1; k >= 0; k--, j++) { if (carry === 0 && j >= length) break; carry += 256 * b58[k]; b58[k] = carry % 58; carry = carry / 58 | 0; } assert(carry === 0); length = j; } i = b58.length - length; while (i < b58.length && b58[i] === 0) i++; let str = ''; for (let j = 0; j < zeroes; j++) str += '1'; for (; i < b58.length; i++) str += base58[b58[i]]; return str; }; if (native) exports.encode = native.toBase58; /** * Decode a base58 string. * @see https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp * @param {Base58String} str * @returns {Buffer} * @throws on non-base58 character. */ exports.decode = function decode(str) { assert(typeof str === 'string'); let zeroes = 0; let i = 0; for (; i < str.length; i++) { if (str[i] !== '1') break; zeroes++; } const b256 = Buffer.allocUnsafe(((str.length * 733) / 1000 | 0) + 1); b256.fill(0); let length = 0; for (; i < str.length; i++) { const ch = unbase58[str[i]]; if (ch == null) throw new Error('Non-base58 character.'); let carry = ch; let j = 0; for (let k = b256.length - 1; k >= 0; k--, j++) { if (carry === 0 && j >= length) break; carry += 58 * b256[k]; b256[k] = carry % 256; carry = carry / 256 | 0; } assert(carry === 0); length = j; } i = 0; while (i < b256.length && b256[i] === 0) i++; const out = Buffer.allocUnsafe(zeroes + (b256.length - i)); let j; for (j = 0; j < zeroes; j++) out[j] = 0; while (i < b256.length) out[j++] = b256[i++]; return out; }; if (native) exports.decode = native.fromBase58; /** * Test whether a string is base58 (note that you * may get a false positive on a hex string). * @param {String?} str * @returns {Boolean} */ exports.isBase58 = function isBase58(str) { return typeof str === 'string' && /^[1-9A-Za-z]+$/.test(str); };