diff --git a/.gitignore b/.gitignore index ff1fec8..8127d8a 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ build # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules +yarn.lock +package-lock.json dist docs diff --git a/src/base32.js b/src/base32.js new file mode 100644 index 0000000..626ee0a --- /dev/null +++ b/src/base32.js @@ -0,0 +1,77 @@ +'use strict' + +function readChar (alphabet, char) { + let idx = alphabet.indexOf(char) + + if (idx === -1) { + throw new Error('invalid character found: ' + char) + } + + return idx +} + +function decode (input, alphabet) { + let length = input.length + + let bits = 0 + let value = 0 + + let index = 0 + let output = new Uint8Array((length * 5 / 8) | 0) + + for (let i = 0; i < length; i++) { + value = (value << 5) | readChar(alphabet, input[i]) + bits += 5 + + if (bits >= 8) { + output[index++] = (value >>> (bits - 8)) & 255 + bits -= 8 + } + } + + return output.buffer +} + +function encode (buffer, alphabet) { + let length = buffer.byteLength + let view = new Uint8Array(buffer) + + let bits = 0 + let value = 0 + let output = '' + + for (let i = 0; i < length; i++) { + value = (value << 8) | view[i] + bits += 8 + + while (bits >= 5) { + output += alphabet[(value >>> (bits - 5)) & 31] + bits -= 5 + } + } + + if (bits > 0) { + output += alphabet[(value << (5 - bits)) & 31] + } + + return output +} + +module.exports = function base32 (alphabet) { + return { + encode (input) { + if (typeof input === 'string') { + return encode(new Buffer(input), alphabet) + } + return encode(input, alphabet) + }, + decode (input) { + for (let char of input) { + if (alphabet.indexOf(char) < 0) { + throw new Error('invalid base32 character') + } + } + return decode(input, alphabet) + } + } +} diff --git a/src/constants.js b/src/constants.js index 2f5509c..bd9aeeb 100644 --- a/src/constants.js +++ b/src/constants.js @@ -3,6 +3,7 @@ const Base = require('./base.js') const baseX = require('base-x') const base16 = require('./base16') +const base32 = require('./base32') // name, code, implementation, alphabet const constants = [ @@ -11,9 +12,9 @@ const constants = [ ['base8', '7', baseX, '01234567'], ['base10', '9', baseX, '0123456789'], ['base16', 'f', base16, '0123456789abcdef'], - ['base32hex', 'v', baseX, '0123456789abcdefghijklmnopqrstuv'], - ['base32', 'b', baseX, 'abcdefghijklmnopqrstuvwxyz234567'], - ['base32z', 'h', baseX, 'ybndrfg8ejkmcpqxot1uwisza345h769'], + ['base32hex', 'v', base32, '0123456789abcdefghijklmnopqrstuv'], + ['base32', 'b', base32, 'abcdefghijklmnopqrstuvwxyz234567'], + ['base32z', 'h', base32, 'ybndrfg8ejkmcpqxot1uwisza345h769'], ['base58flickr', 'Z', baseX, '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'], ['base58btc', 'z', baseX, '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'], ['base64', 'm', baseX, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'], diff --git a/test/multibase.spec.js b/test/multibase.spec.js index 58fb0da..4713475 100644 --- a/test/multibase.spec.js +++ b/test/multibase.spec.js @@ -19,8 +19,23 @@ const supportedBases = [ ['base16', 'yes mani !', 'f796573206d616e692021'], ['base16', new Buffer([0x01]), 'f01'], ['base16', new Buffer([15]), 'f0f'], - ['base32hex', 'yes mani !', 'vf5in683dc5n6i811'], + ['base32', 'yes mani !', 'bpfsxgidnmfxgsibb'], + ['base32', 'f', 'bmy'], + ['base32', 'fo', 'bmzxq'], + ['base32', 'foo', 'bmzxw6'], + ['base32', 'foob', 'bmzxw6yq'], + ['base32', 'fooba', 'bmzxw6ytb'], + ['base32', 'foobar', 'bmzxw6ytboi'], + + ['base32hex', 'yes mani !', 'vf5in683dc5n6i811'], + ['base32hex', 'f', 'vco'], + ['base32hex', 'fo', 'vcpng'], + ['base32hex', 'foo', 'vcpnmu'], + ['base32hex', 'foob', 'vcpnmuog'], + ['base32hex', 'fooba', 'vcpnmuoj1'], + ['base32hex', 'foobar', 'vcpnmuoj1e8'], + ['base32z', 'yes mani !', 'hxf1zgedpcfzg1ebb'], ['base58flickr', 'yes mani !', 'Z7Pznk19XTTzBtx'], ['base58btc', 'yes mani !', 'z7paNL19xttacUY'],