You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.7 KiB
116 lines
2.7 KiB
var crypto = require('crypto');
|
|
var bignum = require('bignum');
|
|
|
|
var globalBuffer = new Buffer(1024);
|
|
var zerobuf = new Buffer(0);
|
|
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
var ALPHABET_ZERO = ALPHABET[0];
|
|
var ALPHABET_BUF = new Buffer(ALPHABET, 'ascii');
|
|
var ALPHABET_INV = {};
|
|
for (var i = 0; i < ALPHABET.length; i++) {
|
|
ALPHABET_INV[ALPHABET[i]] = i;
|
|
};
|
|
|
|
// Vanilla Base58 Encoding
|
|
var base58 = {
|
|
encode: function(buf) {
|
|
var str;
|
|
var x = bignum.fromBuffer(buf);
|
|
var r;
|
|
|
|
if (buf.length < 512) {
|
|
str = globalBuffer;
|
|
} else {
|
|
str = new Buffer(buf.length << 1);
|
|
}
|
|
var i = str.length - 1;
|
|
while (x.gt(0)) {
|
|
r = x.mod(58);
|
|
x = x.div(58);
|
|
str[i] = ALPHABET_BUF[r.toNumber()];
|
|
i--;
|
|
}
|
|
|
|
// deal with leading zeros
|
|
var j = 0;
|
|
while (buf[j] == 0) {
|
|
str[i] = ALPHABET_BUF[0];
|
|
j++;
|
|
i--;
|
|
}
|
|
|
|
return str.slice(i + 1, str.length).toString('ascii');
|
|
},
|
|
|
|
decode: function(str) {
|
|
if (str.length == 0) return zerobuf;
|
|
var answer = bignum(0);
|
|
for (var i = 0; i < str.length; i++) {
|
|
answer = answer.mul(58);
|
|
answer = answer.add(ALPHABET_INV[str[i]]);
|
|
};
|
|
var i = 0;
|
|
while (i < str.length && str[i] == ALPHABET_ZERO) {
|
|
i++;
|
|
}
|
|
if (i > 0) {
|
|
var zb = new Buffer(i);
|
|
zb.fill(0);
|
|
if (i == str.length) return zb;
|
|
answer = answer.toBuffer();
|
|
return Buffer.concat([zb, answer], i + answer.length);
|
|
} else {
|
|
return answer.toBuffer();
|
|
}
|
|
},
|
|
};
|
|
|
|
// Base58Check Encoding
|
|
function sha256(data) {
|
|
return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary');
|
|
};
|
|
|
|
function doubleSHA256(data) {
|
|
return sha256(sha256(data));
|
|
};
|
|
|
|
var base58Check = {
|
|
encode: function(buf) {
|
|
var checkedBuf = new Buffer(buf.length + 4);
|
|
var hash = doubleSHA256(buf);
|
|
buf.copy(checkedBuf);
|
|
hash.copy(checkedBuf, buf.length);
|
|
return base58.encode(checkedBuf);
|
|
},
|
|
|
|
decode: function(s) {
|
|
var buf = base58.decode(s);
|
|
if (buf.length < 4) {
|
|
throw new Error("invalid input: too short");
|
|
}
|
|
|
|
var data = buf.slice(0, -4);
|
|
var csum = buf.slice(-4);
|
|
|
|
var hash = doubleSHA256(data);
|
|
var hash4 = hash.slice(0, 4);
|
|
|
|
if (csum.toString('hex') !== hash4.toString('hex')) {
|
|
throw new Error("checksum mismatch");
|
|
}
|
|
|
|
return data;
|
|
},
|
|
};
|
|
|
|
// if you frequently do base58 encodings with data larger
|
|
// than 512 bytes, you can use this method to expand the
|
|
// size of the reusable buffer
|
|
exports.setBuffer = function(buf) {
|
|
globalBuffer = buf;
|
|
};
|
|
|
|
exports.base58 = base58;
|
|
exports.base58Check = base58Check;
|
|
exports.encode = base58.encode;
|
|
exports.decode = base58.decode;
|
|
|