/ref/javascript/bech32.js
https://github.com/sipa/bech32 · JavaScript · 131 lines · 102 code · 10 blank · 19 comment · 28 complexity · ac69e12737ac30cf5046bff9b0b2b873 MD5 · raw file
- // Copyright (c) 2017, 2021 Pieter Wuille
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- var CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
- var GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
- const encodings = {
- BECH32: "bech32",
- BECH32M: "bech32m",
- };
- module.exports = {
- decode: decode,
- encode: encode,
- encodings: encodings,
- };
- function getEncodingConst (enc) {
- if (enc == encodings.BECH32) {
- return 1;
- } else if (enc == encodings.BECH32M) {
- return 0x2bc830a3;
- } else {
- return null;
- }
- }
- function polymod (values) {
- var chk = 1;
- for (var p = 0; p < values.length; ++p) {
- var top = chk >> 25;
- chk = (chk & 0x1ffffff) << 5 ^ values[p];
- for (var i = 0; i < 5; ++i) {
- if ((top >> i) & 1) {
- chk ^= GENERATOR[i];
- }
- }
- }
- return chk;
- }
- function hrpExpand (hrp) {
- var ret = [];
- var p;
- for (p = 0; p < hrp.length; ++p) {
- ret.push(hrp.charCodeAt(p) >> 5);
- }
- ret.push(0);
- for (p = 0; p < hrp.length; ++p) {
- ret.push(hrp.charCodeAt(p) & 31);
- }
- return ret;
- }
- function verifyChecksum (hrp, data, enc) {
- return polymod(hrpExpand(hrp).concat(data)) === getEncodingConst(enc);
- }
- function createChecksum (hrp, data, enc) {
- var values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
- var mod = polymod(values) ^ getEncodingConst(enc);
- var ret = [];
- for (var p = 0; p < 6; ++p) {
- ret.push((mod >> 5 * (5 - p)) & 31);
- }
- return ret;
- }
- function encode (hrp, data, enc) {
- var combined = data.concat(createChecksum(hrp, data, enc));
- var ret = hrp + '1';
- for (var p = 0; p < combined.length; ++p) {
- ret += CHARSET.charAt(combined[p]);
- }
- return ret;
- }
- function decode (bechString, enc) {
- var p;
- var has_lower = false;
- var has_upper = false;
- for (p = 0; p < bechString.length; ++p) {
- if (bechString.charCodeAt(p) < 33 || bechString.charCodeAt(p) > 126) {
- return null;
- }
- if (bechString.charCodeAt(p) >= 97 && bechString.charCodeAt(p) <= 122) {
- has_lower = true;
- }
- if (bechString.charCodeAt(p) >= 65 && bechString.charCodeAt(p) <= 90) {
- has_upper = true;
- }
- }
- if (has_lower && has_upper) {
- return null;
- }
- bechString = bechString.toLowerCase();
- var pos = bechString.lastIndexOf('1');
- if (pos < 1 || pos + 7 > bechString.length || bechString.length > 90) {
- return null;
- }
- var hrp = bechString.substring(0, pos);
- var data = [];
- for (p = pos + 1; p < bechString.length; ++p) {
- var d = CHARSET.indexOf(bechString.charAt(p));
- if (d === -1) {
- return null;
- }
- data.push(d);
- }
- if (!verifyChecksum(hrp, data, enc)) {
- return null;
- }
- return {hrp: hrp, data: data.slice(0, data.length - 6)};
- }