diff --git a/package-lock.json b/package-lock.json
index 61badf1cd1a7b7f9d947ae1d1d545409957664ef..6c3db0b683dee3a828a58ea67f6939757be8fb42 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -547,6 +547,19 @@
         "defer-to-connect": "^1.0.1"
       }
     },
+    "@thi.ng/base-n": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/@thi.ng/base-n/-/base-n-0.1.6.tgz",
+      "integrity": "sha512-vvN0bhnSbuqk7i4BAeajdqZYwfqN4ESZjC/F216AXtg66BUhQp3zuIZh5u1PEsvFr59Z2T8U6HJgT5/PY0daxg==",
+      "requires": {
+        "@thi.ng/hex": "^0.2.5"
+      }
+    },
+    "@thi.ng/hex": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmjs.org/@thi.ng/hex/-/hex-0.2.5.tgz",
+      "integrity": "sha512-ziJHsLH7zUBjDlZD+q+HszUVMfx9uFE+spSrRTSnt4/fCmXuUxn6hlMAskGifNGBzpE4LB40OG1nvE+0kSYdDw=="
+    },
     "@types/glob": {
       "version": "7.1.3",
       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -1084,6 +1097,14 @@
         "yargs": "^16.2.0"
       }
     },
+    "b58": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/b58/-/b58-4.0.3.tgz",
+      "integrity": "sha512-VDtdiomm0ywbL8YzgevOZ9pcx6LuOZ3d9qYTPDcYUPf7dRYNA8wvK6epYy0FKMWIM5uaDwd3kWt1x+1S9scB1Q==",
+      "requires": {
+        "base-x": "^3.0.2"
+      }
+    },
     "babel-walk": {
       "version": "3.0.0-canary-5",
       "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz",
@@ -1166,6 +1187,14 @@
         }
       }
     },
+    "base-x": {
+      "version": "3.0.8",
+      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz",
+      "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==",
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
     "base64-js": {
       "version": "1.5.1",
       "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -1355,6 +1384,14 @@
         "node-releases": "^1.1.70"
       }
     },
+    "bs58": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
+      "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=",
+      "requires": {
+        "base-x": "^3.0.2"
+      }
+    },
     "buf-compare": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/buf-compare/-/buf-compare-1.0.1.tgz",
@@ -6934,8 +6971,7 @@
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safe-regex": {
       "version": "2.1.1",
diff --git a/package.json b/package.json
index c6bf3850757f2396b96c6ff5020fc8985f3c2a61..b12f244c89b7da767181d05ea0213fd5f59c3909 100644
--- a/package.json
+++ b/package.json
@@ -5,26 +5,27 @@
     "postinstall": "run-s clean build",
     "clean": "rm -rf generated*",
     "build": "run-s build:**",
-		"build:mk:npm": "mkdirp generated/npm",
-		"build:mk:cov-env": "mkdirp generated/cov-env",
-		"build:mk:minfied": "mkdirp generated/minified",
+    "build:mk:npm": "mkdirp generated/npm",
+    "build:mk:cov-env": "mkdirp generated/cov-env",
+    "build:mk:minfied": "mkdirp generated/minified",
     "build:mk:vendors": "mkdirp generated/vendors",
     "build:vendors": "node CI/build.js",
     "build:npm:all": "rollup src/all.mjs --format esm --file generated/npm/all.mjs",
-    "build:npm:crypto": "rollup src/crypto.mjs --format esm --file generated/npm/crypto.mjs",
+		"build:npm:basex": "rollup src/basex.mjs --format esm --file generated/npm/basex.mjs",
+		"build:npm:crypto": "rollup src/crypto.mjs --format esm --file generated/npm/crypto.mjs",
     "build:npm:dictionaryBuilder": "rollup src/dictionary-builder.mjs --format esm --file generated/npm/dictionary-builder.mjs",
-		"build:npm:cp": "cp npm/* generated/npm/",
-		"build:npm:cp:readme": "cp README* generated/npm/",
-		"build:npm:test2npm": "node CI/gen-prod-test.js",
-		"xbuild:npm:coverageForDeadCodeDeletion": "cd generated/npm/ && c8 ava",
-
-		"build:npm:min:all": "terser generated/npm/all.mjs -o generated/minified/all.mjs",
-    "build:npm:min:crypto": "terser generated/npm/crypto.mjs -o generated/minified/crypto.mjs",
+    "build:npm:cp": "cp npm/* generated/npm/",
+    "build:npm:cp:readme": "cp README* generated/npm/",
+    "build:npm:test2npm": "node CI/gen-prod-test.js",
+    "xbuild:npm:coverageForDeadCodeDeletion": "cd generated/npm/ && c8 ava",
+    "build:npm:min:all": "terser generated/npm/all.mjs -o generated/minified/all.mjs",
+		"build:npm:min:basex": "terser generated/npm/basex.mjs -o generated/minified/basex.mjs",
+		"build:npm:min:crypto": "terser generated/npm/crypto.mjs -o generated/minified/crypto.mjs",
     "build:npm:min:dictionaryBuilder": "terser generated/npm/dictionary-builder.mjs -o generated/minified/dictionary-builder.mjs",
     "test": "run-s test:dev",
     "test:dev": "run-p test:dev:**",
     "test:dev:qualityCheck": "xo",
-    "test:dev:runTests": "ava",
+    "test:dev:runTests": "ava src/**.test.mjs",
     "test:dev:duplication": "jscpd ./ -s",
     "xtest:dev:complexity": "codehawk ./",
     "test:production": "run-s test:production:**",
@@ -33,13 +34,17 @@
     "test:production:complexity": "./node_modules/.bin/es6-plato -r -d generated/maintainability ./src/*",
     "test:production:complexity:badgesAndThreshold": "node CI/plato-badges.js",
     "test:production:srcCoverage": "cd generated/cov-env/ && c8 ava",
-		"test:production:testMinified": "cd generated/npm/ && cp -rf ../minified/* ./ && ava",
+    "test:production:testMinified": "cd generated/npm/ && cp -rf ../minified/* ./ && ava",
     "test:production:clean": "rm -rf generated/npm/*.test.mjs generated/npm/node_modules"
   },
   "dependencies": {
+    "@thi.ng/base-n": "^0.1.6",
+    "b58": "^4.0.3",
+    "base-x": "^3.0.8",
+    "bs58": "^4.0.1",
+    "latinize-to-ascii": "^0.5.2",
     "scrypt-async-modern": "^3.0.12",
-    "tweetnacl": "^1.0.3",
-    "latinize-to-ascii": "^0.5.2"
+    "tweetnacl": "^1.0.3"
   },
   "devDependencies": {
     "@jscpd/badge-reporter": "^3.3.23",
@@ -58,31 +63,31 @@
     "ecma-nacl": "^2.5.0",
     "codehawk-cli": "^6.0.3"
   },
-	"ava": {},
-	"c8": {
-		"all": true,
-		"branches": 0.080,
-		"lines": 0.080,
-		"functions": 0.080,
-		"statements": 0.080,
-		"report-dir": "../coverage",
-		"temp-dir": "../nyc_output.temp",
-		"reporter": [
-			"text-summary",
-			"html"
-		]
-	},
+  "ava": {},
+  "c8": {
+    "all": true,
+    "branches": 0.08,
+    "lines": 0.08,
+    "functions": 0.08,
+    "statements": 0.08,
+    "report-dir": "../coverage",
+    "temp-dir": "../nyc_output.temp",
+    "reporter": [
+      "text-summary",
+      "html"
+    ]
+  },
   "xo": {
     "rules": {
       "curly": 0,
-			"unicorn/no-reduce": 0,
-			"unicorn/no-array-reduce": 0,
-			"unicorn/no-array-for-each": 0,
-			"unicorn/prefer-string-slice": 0,
-			"unicorn/prevent-abbreviations": 0,
-			"unicorn/number-literal-case": 0,
-			"unicorn/no-array-callback-reference": 0,
-			"guard-for-in": 0
+      "unicorn/no-reduce": 0,
+      "unicorn/no-array-reduce": 0,
+      "unicorn/no-array-for-each": 0,
+      "unicorn/prefer-string-slice": 0,
+      "unicorn/prevent-abbreviations": 0,
+      "unicorn/number-literal-case": 0,
+      "unicorn/no-array-callback-reference": 0,
+      "guard-for-in": 0
     }
   },
   "maintainabilityThreshold": {
diff --git a/src/all.mjs b/src/all.mjs
index 5e7b608d611b92edc6ab45c512d4a8f946048ea5..b63309923ed3347382789537f4dbc56695a65ed9 100644
--- a/src/all.mjs
+++ b/src/all.mjs
@@ -1,4 +1,5 @@
+import * as basex from './basex.mjs';
 import * as crypto from './crypto.mjs';
 import * as dictionaryBuilder from './dictionary-builder.mjs';
 
-export {crypto, dictionaryBuilder};
+export {basex, crypto, dictionaryBuilder};
diff --git a/src/basex.mjs b/src/basex.mjs
new file mode 100644
index 0000000000000000000000000000000000000000..d09e9e8c1b9fc54da1a7b3a12b8cf4b32d75c09f
--- /dev/null
+++ b/src/basex.mjs
@@ -0,0 +1,70 @@
+// Inspired by bs58, base-x then @thi.ng/base-n module
+const B58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
+export const b58 = basex(B58_ALPHABET);
+export const b16 = basex('0123456789abcdef');
+
+export default function basex(ALPHABET) {
+	const ALPHABET_MAP = {};
+	const BASE = ALPHABET.length;
+	const LEADER = ALPHABET.charAt(0);
+	// Pre-compute lookup table
+	for (let z = 0; z < ALPHABET.length; z++) {
+		const x = ALPHABET.charAt(z);
+		if (ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous');
+		ALPHABET_MAP[x] = z;
+	}
+
+	function encode(source) {
+		if (source.length === 0) return '';
+		const digits = [0];
+		for (let carry of source) {
+			for (let j = 0; j < digits.length; ++j) {
+				carry += digits[j] << 8;
+				digits[j] = carry % BASE;
+				carry = (carry / BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
+			}
+
+			while (carry > 0) {
+				digits.push(carry % BASE);
+				carry = (carry / BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
+			}
+		}
+
+		let string = '';
+		for (let k = 0; source[k] === 0 && k < source.length - 1; ++k) string += LEADER; // Deal with leading zeros
+		for (let q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]]; // Convert digits to a string
+		return string;
+	}
+
+	function decodeUnsafe(string) {
+		if (typeof string !== 'string') throw new TypeError('Expected String');
+		if (string.length === 0) return new Uint8Array(0);
+		const bytes = [0];
+		for (const chr of string) {
+			const value = ALPHABET_MAP[chr];
+			if (value === undefined) return;
+			let carry = value;
+			for (let j = 0; j < bytes.length; ++j) {
+				carry += bytes[j] * BASE;
+				bytes[j] = carry & 0xff;
+				carry >>= 8;
+			}
+
+			while (carry > 0) {
+				bytes.push(carry & 0xff);
+				carry >>= 8;
+			}
+		}
+
+		for (let k = 0; string[k] === LEADER && k < string.length - 1; ++k) bytes.push(0); // Deal with leading zeros
+		return new Uint8Array(bytes.reverse());
+	}
+
+	function decode(string) {
+		const buffer = decodeUnsafe(string);
+		if (buffer) return buffer;
+		throw new Error('Non-base' + BASE + ' character');
+	}
+
+	return {encode, decodeUnsafe, decode};
+}
diff --git a/src/basex.test.mjs b/src/basex.test.mjs
new file mode 100644
index 0000000000000000000000000000000000000000..9971b3e9b0c072f5db4f82b41ea0686d6e369502
--- /dev/null
+++ b/src/basex.test.mjs
@@ -0,0 +1,9 @@
+import test from 'ava';
+import * as app from './basex.mjs';
+
+// Base58
+const pubKey = 'AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG';
+
+test('b58 should decode/encode well', t => {
+	t.is(app.b58.encode(app.b58.decode(pubKey)), pubKey);
+});
diff --git a/src/crypto.mjs b/src/crypto.mjs
index 9f2cff1091d2d0bf6985407fc82167609a1690d0..f75a50b197414407fd60bd01fb74e4011d89ad3f 100644
--- a/src/crypto.mjs
+++ b/src/crypto.mjs
@@ -1,7 +1,8 @@
-export {b58, b16, saltPass2seed, seed2keyPair, idSecPass2rawAll, raw2b58, idSecPass2cleanKeys};
+export {b58, saltPass2seed, seed2keyPair, idSecPass2rawAll, raw2b58, idSecPass2cleanKeys};
 // Alt deps :  import {generate_keypair} from "ecma-nacl/build/lib/signing/sign.js";
 // Alt deps :  import scrypt from "ecma-nacl/build/lib/scrypt/scrypt.js";
 import nacl from '../generated/vendors/nacl.mjs';
+import {b58} from './basex.mjs';
 
 const generateKeypair = nacl.sign.keyPair.fromSeed;
 import scrypt from '../generated/vendors/scrypt.mjs';
@@ -41,74 +42,3 @@ async function saltPass2seed(idSec, pass) {
 	};
 	return scrypt(pass.normalize('NFKC'), idSec.normalize('NFKC'), options);
 }
-
-// Inspired by bs58 and base-x module
-const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
-const b58 = basex(ALPHABET);
-const b16 = basex('0123456789abcdef');
-
-function basex(ALPHABET) {
-	const ALPHABET_MAP = {};
-	const BASE = ALPHABET.length;
-	const LEADER = ALPHABET.charAt(0);
-	// Pre-compute lookup table
-	for (let z = 0; z < ALPHABET.length; z++) {
-		const x = ALPHABET.charAt(z);
-		if (ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous');
-		ALPHABET_MAP[x] = z;
-	}
-
-	function encode(source) {
-		if (source.length === 0) return '';
-		const digits = [0];
-		for (let carry of source) {
-			for (let j = 0; j < digits.length; ++j) {
-				carry += digits[j] << 8;
-				digits[j] = carry % BASE;
-				carry = (carry / BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
-			}
-
-			while (carry > 0) {
-				digits.push(carry % BASE);
-				carry = (carry / BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
-			}
-		}
-
-		let string = '';
-		for (let k = 0; source[k] === 0 && k < source.length - 1; ++k) string += LEADER; // Deal with leading zeros
-		for (let q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]]; // Convert digits to a string
-		return string;
-	}
-
-	function decodeUnsafe(string) {
-		if (typeof string !== 'string') throw new TypeError('Expected String');
-		if (string.length === 0) return new Uint8Array(0);
-		const bytes = [0];
-		for (const chr of string) {
-			const value = ALPHABET_MAP[chr];
-			if (value === undefined) return;
-			let carry = value;
-			for (let j = 0; j < bytes.length; ++j) {
-				carry += bytes[j] * BASE;
-				bytes[j] = carry & 0xff;
-				carry >>= 8;
-			}
-
-			while (carry > 0) {
-				bytes.push(carry & 0xff);
-				carry >>= 8;
-			}
-		}
-
-		for (let k = 0; string[k] === LEADER && k < string.length - 1; ++k) bytes.push(0); // Deal with leading zeros
-		return new Uint8Array(bytes.reverse());
-	}
-
-	function decode(string) {
-		const buffer = decodeUnsafe(string);
-		if (buffer) return buffer;
-		throw new Error('Non-base' + BASE + ' character');
-	}
-
-	return {encode, decodeUnsafe, decode};
-}