├── .editorconfig
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── dist
├── crypto-address-validator.js
└── crypto-address-validator.min.js
├── karma.conf.js
├── package-lock.json
├── package.json
├── src
├── bch_validator.js
├── crypto
│ ├── base58.js
│ ├── blake.js
│ ├── blake224.js
│ ├── blake256.js
│ ├── blake384.js
│ ├── blake512.js
│ ├── convert.js
│ ├── sha3.js
│ └── utils.js
├── crypto_address_validator.js
├── currencies.js
├── ethereum_validator.js
├── nem_validator.js
└── ripple_validator.js
└── test
└── crypto_address_validator.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 4
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | bower_components
3 | .idea
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | addons:
3 | chrome: stable
4 | language: node_js
5 | node_js:
6 | - "4"
7 | - "6"
8 | - "8"
9 | - "9"
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Roman Shtylman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # crypto-address-validator
2 | Simple wallet address validator for validating Bitcoin and other altcoins addresses in **Node.js and browser**.
3 |
4 | Forked from [ognus/wallet-address-validator](https://github.com/ognus/wallet-address-validator).
5 |
6 | **File size is ~201 KB (minifed)**.
7 |
8 | ## Installation
9 |
10 | ### NPM
11 | ```
12 | npm install cryptocurrency-address-validator
13 | ```
14 |
15 | ### Browser
16 | ```html
17 |
18 | ```
19 |
20 | ## API
21 |
22 | ##### validate (address [, currency = 'bitcoin'[, networkType = 'prod']])
23 |
24 | ###### Parameters
25 | * address - Wallet address to validate.
26 | * currency - Optional. Currency name or symbol, e.g. `'bitcoin'` (default), `'litecoin'` or `'LTC'`
27 | * networkType - Optional. Use `'prod'` (default) to enforce standard address, `'testnet'` to enforce testnet address and `'both'` to enforce nothing.
28 |
29 | > Returns true if the address (string) is a valid wallet address for the crypto currency specified, see below for supported currencies.
30 |
31 | ##### getAddressType (address)
32 |
33 | ###### Parameters
34 | * address - Wallet address.
35 |
36 | > Returns address type (as 2 character hex string) if valid base58 address, otherwise null.
37 |
38 | ### Supported crypto currencies
39 |
40 | * Auroracoin/AUR, `'auroracoin'` or `'AUR'`
41 | * BeaverCoin/BVC, `'beavercoin'` or `'BVC'`
42 | * Biocoin/BIO, `'biocoin'` or `'BIO'`
43 | * Bitcoin/BTC, `'bitcoin'` or `'BTC'`
44 | * BitcoinCash/BCH, `'bitcoincash'` or `'BCH'`
45 | * BitcoinGold/BTG, `'bitcoingold'` or `'BTG'`
46 | * BitcoinPrivate/BTCP, `'bitcoinprivate'` or `'BTCP'`
47 | * BitcoinZ/BTCZ, `'bitcoinz'` or `'BTCZ'`
48 | * Callisto/CLO, `'callisto'` or `'CLO'`
49 | * Cardano/ADA, `'cardano'` or `'ADA'`
50 | * Dash/DASH, `'dash'` or `'DASH'`
51 | * Decred/DCR, `'decred'` or `'DCR'`
52 | * Digibyte/DGB, `'digibyte'` or `'DGB'`
53 | * Dogecoin/DOGE, `'dogecoin'` or `'DOGE'`
54 | * Eos/EOS, `'eos'` or `'EOS'`
55 | * Ethereum/ETH, `'ethereum'` or `'ETH'`
56 | * EthereumClassic/ETH, `'ethereumclassic'` or `'ETC'`
57 | * EthereumZero/ETZ, `'etherzero'` or `'ETZ'`
58 | * Freicoin/FRC, `'freicoin'` or `'FRC'`
59 | * Garlicoin/GRLC, `'garlicoin'` or `'GRLC'`
60 | * Hush/HUSH, `'hush'` or `'HUSH'`
61 | * Komodo/KMD, `'komodo'` or `'KMD'`
62 | * Iota/IOTA, `'iota'` or `'IOTA'`
63 | * Icon/ICON, `'icon'` or `'ICON'`
64 | * Litecoin/LTC, `'litecoin'` or `'LTC'`
65 | * Megacoin/MEC, `'megacoin'` or `'MEC'`
66 | * Monero/XWR, `'monero'` or `'XMR'`
67 | * Namecoin/NMC, `'namecoin'` or `'NMC'`
68 | * Nano/NANO, `'nano'` or `'NANO'`
69 | * Neo/NEO, `'neo'` or `'NEO'`
70 | * NeoGas/GAS, `'neogas'` or `'GAS'`
71 | * Nem/NEM, `'nem'` or `'nem'`
72 | * Peercoin/PPCoin/PPC, `'peercoin'` or `'PPC'`
73 | * Primecoin/XPM, `'primecoin'` or `'XPM'`
74 | * Protoshares/PTS, `'protoshares'` or `'PTS'`
75 | * Qash/QASH, `'qash'` or `'QASH'`
76 | * Qtum/QTUM, `'qtum'` or `'QTUM'`
77 | * Railblocks/XRB), `'railblocks'` or `'XRB'`
78 | * RepublicProtocol/REN, `'republicprotocol'` or `'REN'`
79 | * Ripple/XRP, `'ripple'` or `'XRP'`
80 | * Snowgem/SNG, `'snowgem'` or `'SNG'`
81 | * StellarLumens/XLM, `'stellarlumens'` or `'XLM'`
82 | * Tronix/TRX, `'tronix'` or `'TRX'`
83 | * Vertcoin/VTC, `'vertcoin'` or `'VTC'`
84 | * VeChain, `'vechain'` or `'VeChain'`
85 | * Votecoin/VTC, `'votecoin'` or `'VOT'`
86 | * Zcash/ZEC, `'zcash'` or `'ZEC'`
87 | * Zclassic/ZCL, `'zclassic'` or `'ZCL'`
88 | * ZenCash/ZEN, `'zencash'` or `'ZEN'`
89 |
90 |
91 | ### Usage example
92 |
93 | #### Node
94 | ```javascript
95 | var CAValidator = require('crypto-address-validator');
96 |
97 | var valid = CAValidator.validate('1KFzzGtDdnq5hrwxXGjwVnKzRbvf8WVxck', 'BTC');
98 | if(valid)
99 | console.log('This is a valid address');
100 | else
101 | console.log('Address INVALID');
102 |
103 | // This will log 'This is a valid address' to the console.
104 | ```
105 |
106 | ```javascript
107 | var CAValidator = require('crypto-address-validator');
108 |
109 | var valid = CAValidator.validate('1KFzzGtDdnq5hrwxXGjwVnKzRbvf8WVxck', 'litecoin', 'testnet');
110 | if(valid)
111 | console.log('This is a valid address');
112 | else
113 | console.log('Address INVALID');
114 |
115 | // As this is a invalid litecoin address 'Address INVALID' will be logged to console.
116 | ```
117 |
118 | #### Browser
119 | ```html
120 |
121 | ```
122 |
123 | ```javascript
124 | // CAValidator is exposed as a global (window.CAValidator)
125 | var valid = CAValidator.validate('1KFzzGtDdnq5hrwxXGjwVnKzRbvf8WVxck', 'bitcoin');
126 | if(valid)
127 | alert('This is a valid address');
128 | else
129 | alert('Address INVALID');
130 |
131 | // This should show a pop up with text 'This is a valid address'.
132 | ```
133 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | module.exports = function (config) {
3 | config.set({
4 | basePath: '',
5 |
6 | frameworks: ['mocha', 'chai'],
7 |
8 | files: [
9 | 'dist/crypto-address-validator.min.js',
10 | 'test/**/*.js'
11 | ],
12 |
13 | reporters: ['progress'],
14 |
15 | port: 9876,
16 |
17 | colors: true,
18 |
19 | logLevel: config.LOG_INFO,
20 |
21 | browsers: ['ChromeHeadless'],
22 |
23 | singleRun: true,
24 |
25 | concurrency: Infinity
26 | })
27 | };
28 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cryptocurrency-address-validator",
3 | "description": "Crypto wallet address validator for Bitcoin and other Altcoins.",
4 | "keywords": [
5 | "auroracoin",
6 | "beavercoin",
7 | "biocoin",
8 | "bitcoingold",
9 | "bitcoin",
10 | "bitcoin cash",
11 | "bitcoinprivate",
12 | "bitcoinz",
13 | "callisto",
14 | "cardano",
15 | "digibyte",
16 | "eos",
17 | "ethereumclassic",
18 | "etherzero",
19 | "freicoin",
20 | "garlicoin",
21 | "hush",
22 | "icon",
23 | "iota",
24 | "megacoin",
25 | "monero",
26 | "namecoin",
27 | "nano",
28 | "nem",
29 | "railblocks",
30 | "peercoin",
31 | "primecoin",
32 | "protoshares",
33 | "qash",
34 | "republicprotocol",
35 | "snowgem",
36 | "stellarlumens",
37 | "tronix",
38 | "tron",
39 | "vertcoin",
40 | "vechain",
41 | "votecoin",
42 | "zclassic",
43 | "zencash",
44 | "litecoin",
45 | "decred",
46 | "dogecoin",
47 | "ethereum",
48 | "ripple",
49 | "dash",
50 | "neo",
51 | "gas",
52 | "komodo",
53 | "zcash",
54 | "qtum",
55 | "altcoin",
56 | "crypto",
57 | "address",
58 | "wallet",
59 | "validator",
60 | "javascript",
61 | "browser",
62 | "nodejs"
63 | ],
64 | "version": "0.1.3",
65 | "author": "Aditio Agung Nugroho ",
66 | "homepage": "https://github.com/aditioan/crypto-address-validator",
67 | "license": "MIT",
68 | "repository": {
69 | "type": "git",
70 | "url": "https://github.com/aditioan/crypto-address-validator.git"
71 | },
72 | "main": "src/crypto_address_validator",
73 | "engines": {
74 | "node": "*"
75 | },
76 | "scripts": {
77 | "bundle": "browserify src/crypto_address_validator.js --standalone CAValidator --outfile dist/crypto-address-validator.js",
78 | "minify": "uglifyjs -c -m -o dist/crypto-address-validator.min.js -- dist/crypto-address-validator.js",
79 | "test:node": "mocha test",
80 | "test:browser": "karma start",
81 | "test": "npm run test:node && npm run test:browser",
82 | "start": "npm run bundle && npm run minify && npm test"
83 | },
84 | "dependencies": {
85 | "base-x": "^3.0.4",
86 | "bchaddrjs": "^0.3.0",
87 | "crypto-js": "^3.1.9-1",
88 | "iota.lib.js": "^0.4.7",
89 | "jssha": "2.3.1",
90 | "uglify-es": "^3.3.9"
91 | },
92 | "devDependencies": {
93 | "browserify": "^15.1.0",
94 | "chai": "^4.1.2",
95 | "karma": "^2.0.0",
96 | "karma-chai": "^0.1.0",
97 | "karma-chrome-launcher": "^2.2.0",
98 | "karma-mocha": "^1.3.0",
99 | "mocha": "^5.0.2",
100 | "uglify-js": "^3.3.13"
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/bch_validator.js:
--------------------------------------------------------------------------------
1 | var bchaddr = require('bchaddrjs');
2 |
3 | var detectAddressFormat = bchaddr.detectAddressFormat;
4 |
5 |
6 | module.exports = {
7 | /**
8 | * ripple address validation
9 | */
10 | isValidAddress: function (address) {
11 | try{
12 | detectAddressFormat(address);
13 | return true;
14 | }catch (e) {
15 | return false;
16 | }
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/crypto/base58.js:
--------------------------------------------------------------------------------
1 | // Base58 encoding/decoding
2 | // Originally written by Mike Hearn for BitcoinJ
3 | // Copyright (c) 2011 Google Inc
4 | // Ported to JavaScript by Stefan Thomas
5 | // Merged Buffer refactorings from base58-native by Stephen Pair
6 | // Copyright (c) 2013 BitPay Inc
7 |
8 | var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
9 | var ALPHABET_MAP = {};
10 | for (var i = 0; i < ALPHABET.length; ++i) {
11 | ALPHABET_MAP[ALPHABET.charAt(i)] = i;
12 | }
13 | var BASE = ALPHABET.length;
14 |
15 | module.exports = {
16 | decode: function(string) {
17 | if (string.length === 0) return [];
18 |
19 | var i, j, bytes = [0];
20 | for (i = 0; i < string.length; ++i) {
21 | var c = string[i];
22 | if (!(c in ALPHABET_MAP)) throw new Error('Non-base58 character');
23 |
24 | for (j = 0; j < bytes.length; ++j) bytes[j] *= BASE
25 | bytes[0] += ALPHABET_MAP[c];
26 |
27 | var carry = 0;
28 | for (j = 0; j < bytes.length; ++j) {
29 | bytes[j] += carry;
30 | carry = bytes[j] >> 8;
31 | bytes[j] &= 0xff
32 | }
33 |
34 | while (carry) {
35 | bytes.push(carry & 0xff);
36 | carry >>= 8;
37 | }
38 | }
39 | // deal with leading zeros
40 | for (i = 0; string[i] === '1' && i < string.length - 1; ++i){
41 | bytes.push(0);
42 | }
43 |
44 | return bytes.reverse();
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/src/crypto/blake.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | function Blake () {}
4 |
5 | Blake.sigma = [
6 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
7 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
8 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
9 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
10 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
11 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
12 | [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
13 | [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
14 | [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
15 | [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
16 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
17 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
18 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
19 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
20 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
21 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9]
22 | ]
23 |
24 | Blake.u256 = [
25 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
26 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
27 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
28 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917
29 | ]
30 |
31 | Blake.u512 = [
32 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
33 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
34 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
35 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
36 | 0x9216d5d9, 0x8979fb1b, 0xd1310ba6, 0x98dfb5ac,
37 | 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
38 | 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7,
39 | 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69
40 | ]
41 |
42 | Blake.padding = new Buffer([
43 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
51 | ])
52 |
53 | Blake.prototype._length_carry = function (arr) {
54 | for (var j = 0; j < arr.length; ++j) {
55 | if (arr[j] < 0x0100000000) break
56 | arr[j] -= 0x0100000000
57 | arr[j + 1] += 1
58 | }
59 | }
60 |
61 | Blake.prototype.update = function (data) {
62 | var block = this._block
63 | var offset = 0
64 |
65 | while (this._blockOffset + data.length - offset >= block.length) {
66 | for (var i = this._blockOffset; i < block.length;) block[i++] = data[offset++]
67 |
68 | this._length[0] += block.length * 8
69 | this._length_carry(this._length)
70 |
71 | this._compress()
72 | this._blockOffset = 0
73 | }
74 |
75 | while (offset < data.length) block[this._blockOffset++] = data[offset++]
76 | }
77 |
78 | module.exports = Blake
79 |
--------------------------------------------------------------------------------
/src/crypto/blake224.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var inherits = require('inherits')
3 | var Blake256 = require('./blake256')
4 |
5 | var zo = new Buffer([0x00])
6 | var oo = new Buffer([0x80])
7 |
8 | function Blake224 () {
9 | Blake256.call(this)
10 |
11 | this._h = [
12 | 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
13 | 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
14 | ]
15 |
16 | this._zo = zo
17 | this._oo = oo
18 | }
19 |
20 | inherits(Blake224, Blake256)
21 |
22 | Blake224.prototype.digest = function () {
23 | this._padding()
24 |
25 | var buffer = new Buffer(28)
26 | for (var i = 0; i < 7; ++i) buffer.writeUInt32BE(this._h[i], i * 4)
27 | return buffer
28 | }
29 |
30 | module.exports = Blake224
31 |
--------------------------------------------------------------------------------
/src/crypto/blake256.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Credits to https://github.com/cryptocoinjs/blake-hash
5 | */
6 | Blake256.sigma = [
7 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
8 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
9 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
10 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
11 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
12 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
13 | [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
14 | [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
15 | [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
16 | [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
17 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
18 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
19 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
20 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
21 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
22 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9]
23 | ]
24 |
25 | Blake256.u256 = [
26 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
27 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
28 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
29 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917
30 | ]
31 |
32 | Blake256.padding = new Buffer([
33 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
41 | ])
42 |
43 | Blake256.prototype._length_carry = function (arr) {
44 | for (var j = 0; j < arr.length; ++j) {
45 | if (arr[j] < 0x0100000000) break
46 | arr[j] -= 0x0100000000
47 | arr[j + 1] += 1
48 | }
49 | }
50 |
51 | Blake256.prototype.update = function (data, encoding) {
52 | data = new Buffer(data, encoding);
53 | var block = this._block
54 | var offset = 0
55 |
56 | while (this._blockOffset + data.length - offset >= block.length) {
57 | for (var i = this._blockOffset; i < block.length;) block[i++] = data[offset++]
58 |
59 | this._length[0] += block.length * 8
60 | this._length_carry(this._length)
61 |
62 | this._compress()
63 | this._blockOffset = 0
64 | }
65 |
66 | while (offset < data.length) block[this._blockOffset++] = data[offset++]
67 | return this;
68 | }
69 |
70 | var zo = new Buffer([0x01])
71 | var oo = new Buffer([0x81])
72 |
73 | function rot (x, n) {
74 | return ((x << (32 - n)) | (x >>> n)) >>> 0
75 | }
76 |
77 | function g (v, m, i, a, b, c, d, e) {
78 | var sigma = Blake256.sigma
79 | var u256 = Blake256.u256
80 |
81 | v[a] = (v[a] + ((m[sigma[i][e]] ^ u256[sigma[i][e + 1]]) >>> 0) + v[b]) >>> 0
82 | v[d] = rot(v[d] ^ v[a], 16)
83 | v[c] = (v[c] + v[d]) >>> 0
84 | v[b] = rot(v[b] ^ v[c], 12)
85 | v[a] = (v[a] + ((m[sigma[i][e + 1]] ^ u256[sigma[i][e]]) >>> 0) + v[b]) >>> 0
86 | v[d] = rot(v[d] ^ v[a], 8)
87 | v[c] = (v[c] + v[d]) >>> 0
88 | v[b] = rot(v[b] ^ v[c], 7)
89 | }
90 |
91 | function Blake256 () {
92 | this._h = [
93 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
94 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
95 | ]
96 |
97 | this._s = [0, 0, 0, 0]
98 |
99 | this._block = new Buffer(64)
100 | this._blockOffset = 0
101 | this._length = [0, 0]
102 |
103 | this._nullt = false
104 |
105 | this._zo = zo
106 | this._oo = oo
107 | }
108 |
109 | Blake256.prototype._compress = function () {
110 | var u256 = Blake256.u256
111 | var v = new Array(16)
112 | var m = new Array(16)
113 | var i
114 |
115 | for (i = 0; i < 16; ++i) m[i] = this._block.readUInt32BE(i * 4)
116 | for (i = 0; i < 8; ++i) v[i] = this._h[i] >>> 0
117 | for (i = 8; i < 12; ++i) v[i] = (this._s[i - 8] ^ u256[i - 8]) >>> 0
118 | for (i = 12; i < 16; ++i) v[i] = u256[i - 8]
119 |
120 | if (!this._nullt) {
121 | v[12] = (v[12] ^ this._length[0]) >>> 0
122 | v[13] = (v[13] ^ this._length[0]) >>> 0
123 | v[14] = (v[14] ^ this._length[1]) >>> 0
124 | v[15] = (v[15] ^ this._length[1]) >>> 0
125 | }
126 |
127 | for (i = 0; i < 14; ++i) {
128 | /* column step */
129 | g(v, m, i, 0, 4, 8, 12, 0)
130 | g(v, m, i, 1, 5, 9, 13, 2)
131 | g(v, m, i, 2, 6, 10, 14, 4)
132 | g(v, m, i, 3, 7, 11, 15, 6)
133 | /* diagonal step */
134 | g(v, m, i, 0, 5, 10, 15, 8)
135 | g(v, m, i, 1, 6, 11, 12, 10)
136 | g(v, m, i, 2, 7, 8, 13, 12)
137 | g(v, m, i, 3, 4, 9, 14, 14)
138 | }
139 |
140 | for (i = 0; i < 16; ++i) this._h[i % 8] = (this._h[i % 8] ^ v[i]) >>> 0
141 | for (i = 0; i < 8; ++i) this._h[i] = (this._h[i] ^ this._s[i % 4]) >>> 0
142 | }
143 |
144 | Blake256.prototype._padding = function () {
145 | var lo = this._length[0] + this._blockOffset * 8
146 | var hi = this._length[1]
147 | if (lo >= 0x0100000000) {
148 | lo -= 0x0100000000
149 | hi += 1
150 | }
151 |
152 | var msglen = new Buffer(8)
153 | msglen.writeUInt32BE(hi, 0)
154 | msglen.writeUInt32BE(lo, 4)
155 |
156 | if (this._blockOffset === 55) {
157 | this._length[0] -= 8
158 | this.update(this._oo)
159 | } else {
160 | if (this._blockOffset < 55) {
161 | if (this._blockOffset === 0) this._nullt = true
162 | this._length[0] -= (55 - this._blockOffset) * 8
163 | this.update(Blake256.padding.slice(0, 55 - this._blockOffset))
164 | } else {
165 | this._length[0] -= (64 - this._blockOffset) * 8
166 | this.update(Blake256.padding.slice(0, 64 - this._blockOffset))
167 | this._length[0] -= 55 * 8
168 | this.update(Blake256.padding.slice(1, 1 + 55))
169 | this._nullt = true
170 | }
171 |
172 | this.update(this._zo)
173 | this._length[0] -= 8
174 | }
175 |
176 | this._length[0] -= 64
177 | this.update(msglen)
178 | }
179 |
180 | Blake256.prototype.digest = function (encoding) {
181 | this._padding()
182 |
183 | var buffer = new Buffer(32)
184 | for (var i = 0; i < 8; ++i) buffer.writeUInt32BE(this._h[i], i * 4)
185 | return buffer.toString(encoding);
186 | }
187 |
188 | module.exports = Blake256;
--------------------------------------------------------------------------------
/src/crypto/blake384.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var inherits = require('inherits')
3 | var Blake512 = require('./blake512')
4 |
5 | var zo = new Buffer([0x00])
6 | var oo = new Buffer([0x80])
7 |
8 | function Blake384 () {
9 | Blake512.call(this)
10 |
11 | this._h = [
12 | 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507,
13 | 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,
14 | 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511,
15 | 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4
16 | ]
17 |
18 | this._zo = zo
19 | this._oo = oo
20 | }
21 |
22 | inherits(Blake384, Blake512)
23 |
24 | Blake384.prototype.digest = function () {
25 | this._padding()
26 |
27 | var buffer = new Buffer(48)
28 | for (var i = 0; i < 12; ++i) buffer.writeUInt32BE(this._h[i], i * 4)
29 | return buffer
30 | }
31 |
32 | module.exports = Blake384
33 |
--------------------------------------------------------------------------------
/src/crypto/blake512.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var inherits = require('inherits')
3 | var Blake = require('./blake')
4 |
5 | var zo = new Buffer([0x01])
6 | var oo = new Buffer([0x81])
7 |
8 | function rot (v, i, j, n) {
9 | var hi = v[i * 2] ^ v[j * 2]
10 | var lo = v[i * 2 + 1] ^ v[j * 2 + 1]
11 |
12 | if (n >= 32) {
13 | lo = lo ^ hi
14 | hi = lo ^ hi
15 | lo = lo ^ hi
16 | n -= 32
17 | }
18 |
19 | if (n === 0) {
20 | v[i * 2] = hi >>> 0
21 | v[i * 2 + 1] = lo >>> 0
22 | } else {
23 | v[i * 2] = ((hi >>> n) | (lo << (32 - n))) >>> 0
24 | v[i * 2 + 1] = ((lo >>> n) | (hi << (32 - n))) >>> 0
25 | }
26 | }
27 |
28 | function g (v, m, i, a, b, c, d, e) {
29 | var sigma = Blake.sigma
30 | var u512 = Blake.u512
31 | var lo
32 |
33 | // v[a] += (m[sigma[i][e]] ^ u512[sigma[i][e+1]]) + v[b];
34 | lo = v[a * 2 + 1] + ((m[sigma[i][e] * 2 + 1] ^ u512[sigma[i][e + 1] * 2 + 1]) >>> 0) + v[b * 2 + 1]
35 | v[a * 2] = (v[a * 2] + ((m[sigma[i][e] * 2] ^ u512[sigma[i][e + 1] * 2]) >>> 0) + v[b * 2] + ~~(lo / 0x0100000000)) >>> 0
36 | v[a * 2 + 1] = lo >>> 0
37 |
38 | // v[d] = ROT( v[d] ^ v[a],32);
39 | rot(v, d, a, 32)
40 |
41 | // v[c] += v[d];
42 | lo = v[c * 2 + 1] + v[d * 2 + 1]
43 | v[c * 2] = (v[c * 2] + v[d * 2] + ~~(lo / 0x0100000000)) >>> 0
44 | v[c * 2 + 1] = lo >>> 0
45 |
46 | // v[b] = ROT( v[b] ^ v[c],25);
47 | rot(v, b, c, 25)
48 |
49 | // v[a] += (m[sigma[i][e+1]] ^ u512[sigma[i][e]])+v[b];
50 | lo = v[a * 2 + 1] + ((m[sigma[i][e + 1] * 2 + 1] ^ u512[sigma[i][e] * 2 + 1]) >>> 0) + v[b * 2 + 1]
51 | v[a * 2] = (v[a * 2] + ((m[sigma[i][e + 1] * 2] ^ u512[sigma[i][e] * 2]) >>> 0) + v[b * 2] + ~~(lo / 0x0100000000)) >>> 0
52 | v[a * 2 + 1] = lo >>> 0
53 |
54 | // v[d] = ROT( v[d] ^ v[a],16);
55 | rot(v, d, a, 16)
56 |
57 | // v[c] += v[d];
58 | lo = v[c * 2 + 1] + v[d * 2 + 1]
59 | v[c * 2] = (v[c * 2] + v[d * 2] + ~~(lo / 0x0100000000)) >>> 0
60 | v[c * 2 + 1] = lo >>> 0
61 |
62 | // v[b] = ROT( v[b] ^ v[c],11)
63 | rot(v, b, c, 11)
64 | }
65 |
66 | function Blake512 () {
67 | Blake.call(this)
68 |
69 | this._h = [
70 | 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b,
71 | 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,
72 | 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f,
73 | 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179
74 | ]
75 |
76 | this._s = [0, 0, 0, 0, 0, 0, 0, 0]
77 |
78 | this._block = new Buffer(128)
79 | this._blockOffset = 0
80 | this._length = [0, 0, 0, 0]
81 |
82 | this._nullt = false
83 |
84 | this._zo = zo
85 | this._oo = oo
86 | }
87 |
88 | inherits(Blake512, Blake)
89 |
90 | Blake512.prototype._compress = function () {
91 | var u512 = Blake.u512
92 | var v = new Array(32)
93 | var m = new Array(32)
94 | var i
95 |
96 | for (i = 0; i < 32; ++i) m[i] = this._block.readUInt32BE(i * 4)
97 | for (i = 0; i < 16; ++i) v[i] = this._h[i] >>> 0
98 | for (i = 16; i < 24; ++i) v[i] = (this._s[i - 16] ^ u512[i - 16]) >>> 0
99 | for (i = 24; i < 32; ++i) v[i] = u512[i - 16]
100 |
101 | if (!this._nullt) {
102 | v[24] = (v[24] ^ this._length[1]) >>> 0
103 | v[25] = (v[25] ^ this._length[0]) >>> 0
104 | v[26] = (v[26] ^ this._length[1]) >>> 0
105 | v[27] = (v[27] ^ this._length[0]) >>> 0
106 | v[28] = (v[28] ^ this._length[3]) >>> 0
107 | v[29] = (v[29] ^ this._length[2]) >>> 0
108 | v[30] = (v[30] ^ this._length[3]) >>> 0
109 | v[31] = (v[31] ^ this._length[2]) >>> 0
110 | }
111 |
112 | for (i = 0; i < 16; ++i) {
113 | /* column step */
114 | g(v, m, i, 0, 4, 8, 12, 0)
115 | g(v, m, i, 1, 5, 9, 13, 2)
116 | g(v, m, i, 2, 6, 10, 14, 4)
117 | g(v, m, i, 3, 7, 11, 15, 6)
118 | /* diagonal step */
119 | g(v, m, i, 0, 5, 10, 15, 8)
120 | g(v, m, i, 1, 6, 11, 12, 10)
121 | g(v, m, i, 2, 7, 8, 13, 12)
122 | g(v, m, i, 3, 4, 9, 14, 14)
123 | }
124 |
125 | for (i = 0; i < 16; ++i) {
126 | this._h[(i % 8) * 2] = (this._h[(i % 8) * 2] ^ v[i * 2]) >>> 0
127 | this._h[(i % 8) * 2 + 1] = (this._h[(i % 8) * 2 + 1] ^ v[i * 2 + 1]) >>> 0
128 | }
129 |
130 | for (i = 0; i < 8; ++i) {
131 | this._h[i * 2] = (this._h[i * 2] ^ this._s[(i % 4) * 2]) >>> 0
132 | this._h[i * 2 + 1] = (this._h[i * 2 + 1] ^ this._s[(i % 4) * 2 + 1]) >>> 0
133 | }
134 | }
135 |
136 | Blake512.prototype._padding = function () {
137 | var len = this._length.slice()
138 | len[0] += this._blockOffset * 8
139 | this._length_carry(len)
140 |
141 | var msglen = new Buffer(16)
142 | for (var i = 0; i < 4; ++i) msglen.writeUInt32BE(len[3 - i], i * 4)
143 |
144 | if (this._blockOffset === 111) {
145 | this._length[0] -= 8
146 | this.update(this._oo)
147 | } else {
148 | if (this._blockOffset < 111) {
149 | if (this._blockOffset === 0) this._nullt = true
150 | this._length[0] -= (111 - this._blockOffset) * 8
151 | this.update(Blake.padding.slice(0, 111 - this._blockOffset))
152 | } else {
153 | this._length[0] -= (128 - this._blockOffset) * 8
154 | this.update(Blake.padding.slice(0, 128 - this._blockOffset))
155 | this._length[0] -= 111 * 8
156 | this.update(Blake.padding.slice(1, 1 + 111))
157 | this._nullt = true
158 | }
159 |
160 | this.update(this._zo)
161 | this._length[0] -= 8
162 | }
163 |
164 | this._length[0] -= 128
165 | this.update(msglen)
166 | }
167 |
168 | Blake512.prototype.digest = function () {
169 | this._padding()
170 |
171 | var buffer = new Buffer(64)
172 | for (var i = 0; i < 16; ++i) buffer.writeUInt32BE(this._h[i], i * 4)
173 | return buffer
174 | }
175 |
176 | module.exports = Blake512
177 |
--------------------------------------------------------------------------------
/src/crypto/convert.js:
--------------------------------------------------------------------------------
1 | var CryptoJS = require('crypto-js');
2 |
3 | const _hexEncodeArray = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
4 |
5 | /**
6 | * Reversed convertion of hex to Uint8Array
7 | *
8 | * @param {string} hexx - An hex string
9 | *
10 | * @return {Uint8Array}
11 | */
12 | let hex2ua_reversed = function(hexx) {
13 | let hex = hexx.toString(); //force conversion
14 | let ua = new Uint8Array(hex.length / 2);
15 | for (let i = 0; i < hex.length; i += 2) {
16 | ua[ua.length - 1 - (i / 2)] = parseInt(hex.substr(i, 2), 16);
17 | }
18 | return ua;
19 | };
20 |
21 | /**
22 | * Convert hex to Uint8Array
23 | *
24 | * @param {string} hexx - An hex string
25 | *
26 | * @return {Uint8Array}
27 | */
28 | let hex2ua = function(hexx) {
29 | let hex = hexx.toString(); //force conversion
30 | let ua = new Uint8Array(hex.length / 2);
31 | for (let i = 0; i < hex.length; i += 2) {
32 | ua[i / 2] = parseInt(hex.substr(i, 2), 16);
33 | }
34 | return ua;
35 | };
36 |
37 | /**
38 | * Convert an Uint8Array to hex
39 | *
40 | * @param {Uint8Array} ua - An Uint8Array
41 | *
42 | * @return {string}
43 | */
44 | let ua2hex = function(ua) {
45 | let s = '';
46 | for (let i = 0; i < ua.length; i++) {
47 | let code = ua[i];
48 | s += _hexEncodeArray[code >>> 4];
49 | s += _hexEncodeArray[code & 0x0F];
50 | }
51 | return s;
52 | };
53 |
54 | /**
55 | * Convert hex to string
56 | *
57 | * @param {string} hexx - An hex string
58 | *
59 | * @return {string}
60 | */
61 | let hex2a = function(hexx) {
62 | let hex = hexx.toString();
63 | let str = '';
64 | for (let i = 0; i < hex.length; i += 2)
65 | str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
66 | return str;
67 | };
68 |
69 | /**
70 | * Convert UTF-8 to hex
71 | *
72 | * @param {string} str - An UTF-8 string
73 | *
74 | * @return {string}
75 | */
76 | let utf8ToHex = function(str) {
77 | let rawString = rstr2utf8(str);
78 | let hex = "";
79 | for (var i = 0; i < rawString.length; i++) {
80 | hex += strlpad(rawString.charCodeAt(i).toString(16), "0", 2)
81 | }
82 | return hex;
83 | };
84 |
85 | // Padding helper for above function
86 | let strlpad = function(str, pad, len) {
87 | while (str.length < len) {
88 | str = pad + str;
89 | }
90 | return str;
91 | }
92 |
93 | /**
94 | * Convert an Uint8Array to WordArray
95 | *
96 | * @param {Uint8Array} ua - An Uint8Array
97 | * @param {number} uaLength - The Uint8Array length
98 | *
99 | * @return {WordArray}
100 | */
101 | let ua2words = function(ua, uaLength) {
102 | let temp = [];
103 | for (let i = 0; i < uaLength; i += 4) {
104 | let x = ua[i] * 0x1000000 + (ua[i + 1] || 0) * 0x10000 + (ua[i + 2] || 0) * 0x100 + (ua[i + 3] || 0);
105 | temp.push((x > 0x7fffffff) ? x - 0x100000000 : x);
106 | }
107 | return CryptoJS.lib.WordArray.create(temp, uaLength);
108 | }
109 |
110 | /**
111 | * Convert a wordArray to Uint8Array
112 | *
113 | * @param {Uint8Array} destUa - A destination Uint8Array
114 | * @param {WordArray} cryptowords - A wordArray
115 | *
116 | * @return {Uint8Array}
117 | */
118 | let words2ua = function(destUa, cryptowords) {
119 | for (let i = 0; i < destUa.length; i += 4) {
120 | let v = cryptowords.words[i / 4];
121 | if (v < 0) v += 0x100000000;
122 | destUa[i] = (v >>> 24);
123 | destUa[i + 1] = (v >>> 16) & 0xff;
124 | destUa[i + 2] = (v >>> 8) & 0xff;
125 | destUa[i + 3] = v & 0xff;
126 | }
127 | return destUa;
128 | }
129 |
130 | /**
131 | * Converts a raw javascript string into a string of single byte characters using utf8 encoding.
132 | * This makes it easier to perform other encoding operations on the string.
133 | *
134 | * @param {string} input - A raw string
135 | *
136 | * @return {string} - UTF-8 string
137 | */
138 | let rstr2utf8 = function (input) {
139 | let output = "";
140 |
141 | for (let n = 0; n < input.length; n++) {
142 | let c = input.charCodeAt(n);
143 |
144 | if (c < 128) {
145 | output += String.fromCharCode(c);
146 | } else if ((c > 127) && (c < 2048)) {
147 | output += String.fromCharCode((c >> 6) | 192);
148 | output += String.fromCharCode((c & 63) | 128);
149 | } else {
150 | output += String.fromCharCode((c >> 12) | 224);
151 | output += String.fromCharCode(((c >> 6) & 63) | 128);
152 | output += String.fromCharCode((c & 63) | 128);
153 | }
154 | }
155 |
156 | return output;
157 | }
158 |
159 | // Does the reverse of rstr2utf8.
160 | let utf82rstr = function (input) {
161 | let output = "", i = 0, c = 0, c1 = 0, c2 = 0, c3 = 0;
162 |
163 | while (i < input.length) {
164 | c = input.charCodeAt(i);
165 |
166 | if (c < 128) {
167 | output += String.fromCharCode(c);
168 | i++;
169 | } else if ((c > 191) && (c < 224)) {
170 | c2 = input.charCodeAt(i + 1);
171 | output += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
172 | i += 2;
173 | } else {
174 | c2 = input.charCodeAt(i + 1);
175 | c3 = input.charCodeAt(i + 2);
176 | output += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
177 | i += 3;
178 | }
179 | }
180 |
181 | return output;
182 | }
183 |
184 | module.exports = {
185 | hex2ua_reversed,
186 | hex2ua,
187 | ua2hex,
188 | hex2a,
189 | utf8ToHex,
190 | ua2words,
191 | words2ua,
192 | rstr2utf8,
193 | utf82rstr
194 | }
--------------------------------------------------------------------------------
/src/crypto/sha3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [js-sha3]{@link https://github.com/emn178/js-sha3}
3 | *
4 | * @version 0.7.0
5 | * @author Chen, Yi-Cyuan [emn178@gmail.com]
6 | * @copyright Chen, Yi-Cyuan 2015-2017
7 | * @license MIT
8 | */
9 | /*jslint bitwise: true */
10 | 'use strict';
11 |
12 | var ERROR = 'input is invalid type';
13 | var WINDOW = typeof window === 'object';
14 | var root = WINDOW ? window : {};
15 | if (root.JS_SHA3_NO_WINDOW) {
16 | WINDOW = false;
17 | }
18 | var WEB_WORKER = !WINDOW && typeof self === 'object';
19 | var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
20 | if (NODE_JS) {
21 | root = global;
22 | } else if (WEB_WORKER) {
23 | root = self;
24 | }
25 | var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
26 | var HEX_CHARS = '0123456789abcdef'.split('');
27 | var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
28 | var CSHAKE_PADDING = [4, 1024, 262144, 67108864];
29 | var KECCAK_PADDING = [1, 256, 65536, 16777216];
30 | var PADDING = [6, 1536, 393216, 100663296];
31 | var SHIFT = [0, 8, 16, 24];
32 | var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
33 | 0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
34 | 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
35 | 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
36 | 2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
37 | var BITS = [224, 256, 384, 512];
38 | var SHAKE_BITS = [128, 256];
39 | var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest'];
40 | var CSHAKE_BYTEPAD = {
41 | '128': 168,
42 | '256': 136
43 | };
44 |
45 | if (root.JS_SHA3_NO_NODE_JS || !Array.isArray) {
46 | Array.isArray = function (obj) {
47 | return Object.prototype.toString.call(obj) === '[object Array]';
48 | };
49 | }
50 |
51 | if (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
52 | ArrayBuffer.isView = function (obj) {
53 | return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
54 | };
55 | }
56 |
57 | var createOutputMethod = function (bits, padding, outputType) {
58 | return function (message) {
59 | return new Keccak(bits, padding, bits).update(message)[outputType]();
60 | };
61 | };
62 |
63 | var createShakeOutputMethod = function (bits, padding, outputType) {
64 | return function (message, outputBits) {
65 | return new Keccak(bits, padding, outputBits).update(message)[outputType]();
66 | };
67 | };
68 |
69 | var createCshakeOutputMethod = function (bits, padding, outputType) {
70 | return function (message, outputBits, n, s) {
71 | return methods['cshake' + bits].update(message, outputBits, n, s)[outputType]();
72 | };
73 | };
74 |
75 | var createKmacOutputMethod = function (bits, padding, outputType) {
76 | return function (key, message, outputBits, s) {
77 | return methods['kmac' + bits].update(key, message, outputBits, s)[outputType]();
78 | };
79 | };
80 |
81 | var createOutputMethods = function (method, createMethod, bits, padding) {
82 | for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
83 | var type = OUTPUT_TYPES[i];
84 | method[type] = createMethod(bits, padding, type);
85 | }
86 | return method;
87 | };
88 |
89 | var createMethod = function (bits, padding) {
90 | var method = createOutputMethod(bits, padding, 'hex');
91 | method.create = function () {
92 | return new Keccak(bits, padding, bits);
93 | };
94 | method.update = function (message) {
95 | return method.create().update(message);
96 | };
97 | return createOutputMethods(method, createOutputMethod, bits, padding);
98 | };
99 |
100 | var createShakeMethod = function (bits, padding) {
101 | var method = createShakeOutputMethod(bits, padding, 'hex');
102 | method.create = function (outputBits) {
103 | return new Keccak(bits, padding, outputBits);
104 | };
105 | method.update = function (message, outputBits) {
106 | return method.create(outputBits).update(message);
107 | };
108 | return createOutputMethods(method, createShakeOutputMethod, bits, padding);
109 | };
110 |
111 | var createCshakeMethod = function (bits, padding) {
112 | var w = CSHAKE_BYTEPAD[bits];
113 | var method = createCshakeOutputMethod(bits, padding, 'hex');
114 | method.create = function (outputBits, n, s) {
115 | if (!n && !s) {
116 | return methods['shake' + bits].create(outputBits);
117 | } else {
118 | return new Keccak(bits, padding, outputBits).bytepad([n, s], w);
119 | }
120 | };
121 | method.update = function (message, outputBits, n, s) {
122 | return method.create(outputBits, n, s).update(message);
123 | };
124 | return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
125 | };
126 |
127 | var createKmacMethod = function (bits, padding) {
128 | var w = CSHAKE_BYTEPAD[bits];
129 | var method = createKmacOutputMethod(bits, padding, 'hex');
130 | method.create = function (key, outputBits, s) {
131 | return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w);
132 | };
133 | method.update = function (key, message, outputBits, s) {
134 | return method.create(key, outputBits, s).update(message);
135 | };
136 | return createOutputMethods(method, createKmacOutputMethod, bits, padding);
137 | };
138 |
139 | var algorithms = [
140 | { name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod },
141 | { name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod },
142 | { name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod },
143 | { name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod },
144 | { name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod }
145 | ];
146 |
147 | var methods = {}, methodNames = [];
148 |
149 | for (var i = 0; i < algorithms.length; ++i) {
150 | var algorithm = algorithms[i];
151 | var bits = algorithm.bits;
152 | for (var j = 0; j < bits.length; ++j) {
153 | var methodName = algorithm.name + '_' + bits[j];
154 | methodNames.push(methodName);
155 | methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding);
156 | if (algorithm.name !== 'sha3') {
157 | var newMethodName = algorithm.name + bits[j];
158 | methodNames.push(newMethodName);
159 | methods[newMethodName] = methods[methodName];
160 | }
161 | }
162 | }
163 |
164 | function Keccak(bits, padding, outputBits) {
165 | this.blocks = [];
166 | this.s = [];
167 | this.padding = padding;
168 | this.outputBits = outputBits;
169 | this.reset = true;
170 | this.finalized = false;
171 | this.block = 0;
172 | this.start = 0;
173 | this.blockCount = (1600 - (bits << 1)) >> 5;
174 | this.byteCount = this.blockCount << 2;
175 | this.outputBlocks = outputBits >> 5;
176 | this.extraBytes = (outputBits & 31) >> 3;
177 |
178 | for (var i = 0; i < 50; ++i) {
179 | this.s[i] = 0;
180 | }
181 | }
182 |
183 | Keccak.prototype.update = function (message) {
184 | if (this.finalized) {
185 | return;
186 | }
187 | var notString, type = typeof message;
188 | if (type !== 'string') {
189 | if (type === 'object') {
190 | if (message === null) {
191 | throw ERROR;
192 | } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
193 | message = new Uint8Array(message);
194 | } else if (!Array.isArray(message)) {
195 | if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
196 | throw ERROR;
197 | }
198 | }
199 | } else {
200 | throw ERROR;
201 | }
202 | notString = true;
203 | }
204 | var blocks = this.blocks, byteCount = this.byteCount, length = message.length,
205 | blockCount = this.blockCount, index = 0, s = this.s, i, code;
206 |
207 | while (index < length) {
208 | if (this.reset) {
209 | this.reset = false;
210 | blocks[0] = this.block;
211 | for (i = 1; i < blockCount + 1; ++i) {
212 | blocks[i] = 0;
213 | }
214 | }
215 | if (notString) {
216 | for (i = this.start; index < length && i < byteCount; ++index) {
217 | blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
218 | }
219 | } else {
220 | for (i = this.start; index < length && i < byteCount; ++index) {
221 | code = message.charCodeAt(index);
222 | if (code < 0x80) {
223 | blocks[i >> 2] |= code << SHIFT[i++ & 3];
224 | } else if (code < 0x800) {
225 | blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
226 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
227 | } else if (code < 0xd800 || code >= 0xe000) {
228 | blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
229 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
230 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
231 | } else {
232 | code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
233 | blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
234 | blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
235 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
236 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
237 | }
238 | }
239 | }
240 | this.lastByteIndex = i;
241 | if (i >= byteCount) {
242 | this.start = i - byteCount;
243 | this.block = blocks[blockCount];
244 | for (i = 0; i < blockCount; ++i) {
245 | s[i] ^= blocks[i];
246 | }
247 | f(s);
248 | this.reset = true;
249 | } else {
250 | this.start = i;
251 | }
252 | }
253 | return this;
254 | };
255 |
256 | Keccak.prototype.encode = function (x, right) {
257 | var o = x & 255, n = 1;
258 | var bytes = [o];
259 | x = x >> 8;
260 | o = x & 255;
261 | while (o > 0) {
262 | bytes.unshift(o);
263 | x = x >> 8;
264 | o = x & 255;
265 | ++n;
266 | }
267 | if (right) {
268 | bytes.push(n);
269 | } else {
270 | bytes.unshift(n);
271 | }
272 | this.update(bytes);
273 | return bytes.length;
274 | };
275 |
276 | Keccak.prototype.encodeString = function (str) {
277 | var notString, type = typeof str;
278 | if (type !== 'string') {
279 | if (type === 'object') {
280 | if (str === null) {
281 | throw ERROR;
282 | } else if (ARRAY_BUFFER && str.constructor === ArrayBuffer) {
283 | str = new Uint8Array(str);
284 | } else if (!Array.isArray(str)) {
285 | if (!ARRAY_BUFFER || !ArrayBuffer.isView(str)) {
286 | throw ERROR;
287 | }
288 | }
289 | } else {
290 | throw ERROR;
291 | }
292 | notString = true;
293 | }
294 | var bytes = 0, length = str.length;
295 | if (notString) {
296 | bytes = length;
297 | } else {
298 | for (var i = 0; i < str.length; ++i) {
299 | var code = str.charCodeAt(i);
300 | if (code < 0x80) {
301 | bytes += 1;
302 | } else if (code < 0x800) {
303 | bytes += 2;
304 | } else if (code < 0xd800 || code >= 0xe000) {
305 | bytes += 3;
306 | } else {
307 | code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));
308 | bytes += 4;
309 | }
310 | }
311 | }
312 | bytes += this.encode(bytes * 8);
313 | this.update(str);
314 | return bytes;
315 | };
316 |
317 | Keccak.prototype.bytepad = function (strs, w) {
318 | var bytes = this.encode(w);
319 | for (var i = 0; i < strs.length; ++i) {
320 | bytes += this.encodeString(strs[i]);
321 | }
322 | var paddingBytes = w - bytes % w;
323 | var zeros = [];
324 | zeros.length = paddingBytes;
325 | this.update(zeros);
326 | return this;
327 | };
328 |
329 | Keccak.prototype.finalize = function () {
330 | if (this.finalized) {
331 | return;
332 | }
333 | this.finalized = true;
334 | var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s;
335 | blocks[i >> 2] |= this.padding[i & 3];
336 | if (this.lastByteIndex === this.byteCount) {
337 | blocks[0] = blocks[blockCount];
338 | for (i = 1; i < blockCount + 1; ++i) {
339 | blocks[i] = 0;
340 | }
341 | }
342 | blocks[blockCount - 1] |= 0x80000000;
343 | for (i = 0; i < blockCount; ++i) {
344 | s[i] ^= blocks[i];
345 | }
346 | f(s);
347 | };
348 |
349 | Keccak.prototype.toString = Keccak.prototype.hex = function () {
350 | this.finalize();
351 |
352 | var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
353 | extraBytes = this.extraBytes, i = 0, j = 0;
354 | var hex = '', block;
355 | while (j < outputBlocks) {
356 | for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
357 | block = s[i];
358 | hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] +
359 | HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] +
360 | HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] +
361 | HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F];
362 | }
363 | if (j % blockCount === 0) {
364 | f(s);
365 | i = 0;
366 | }
367 | }
368 | if (extraBytes) {
369 | block = s[i];
370 | hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
371 | if (extraBytes > 1) {
372 | hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
373 | }
374 | if (extraBytes > 2) {
375 | hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F];
376 | }
377 | }
378 | return hex;
379 | };
380 |
381 | Keccak.prototype.arrayBuffer = function () {
382 | this.finalize();
383 |
384 | var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
385 | extraBytes = this.extraBytes, i = 0, j = 0;
386 | var bytes = this.outputBits >> 3;
387 | var buffer;
388 | if (extraBytes) {
389 | buffer = new ArrayBuffer((outputBlocks + 1) << 2);
390 | } else {
391 | buffer = new ArrayBuffer(bytes);
392 | }
393 | var array = new Uint32Array(buffer);
394 | while (j < outputBlocks) {
395 | for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
396 | array[j] = s[i];
397 | }
398 | if (j % blockCount === 0) {
399 | f(s);
400 | }
401 | }
402 | if (extraBytes) {
403 | array[i] = s[i];
404 | buffer = buffer.slice(0, bytes);
405 | }
406 | return buffer;
407 | };
408 |
409 | Keccak.prototype.buffer = Keccak.prototype.arrayBuffer;
410 |
411 | Keccak.prototype.digest = Keccak.prototype.array = function () {
412 | this.finalize();
413 |
414 | var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
415 | extraBytes = this.extraBytes, i = 0, j = 0;
416 | var array = [], offset, block;
417 | while (j < outputBlocks) {
418 | for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
419 | offset = j << 2;
420 | block = s[i];
421 | array[offset] = block & 0xFF;
422 | array[offset + 1] = (block >> 8) & 0xFF;
423 | array[offset + 2] = (block >> 16) & 0xFF;
424 | array[offset + 3] = (block >> 24) & 0xFF;
425 | }
426 | if (j % blockCount === 0) {
427 | f(s);
428 | }
429 | }
430 | if (extraBytes) {
431 | offset = j << 2;
432 | block = s[i];
433 | array[offset] = block & 0xFF;
434 | if (extraBytes > 1) {
435 | array[offset + 1] = (block >> 8) & 0xFF;
436 | }
437 | if (extraBytes > 2) {
438 | array[offset + 2] = (block >> 16) & 0xFF;
439 | }
440 | }
441 | return array;
442 | };
443 |
444 | function Kmac(bits, padding, outputBits) {
445 | Keccak.call(this, bits, padding, outputBits);
446 | }
447 |
448 | Kmac.prototype = new Keccak();
449 |
450 | Kmac.prototype.finalize = function () {
451 | this.encode(this.outputBits, true);
452 | return Keccak.prototype.finalize.call(this);
453 | };
454 |
455 | var f = function (s) {
456 | var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,
457 | b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17,
458 | b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33,
459 | b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49;
460 | for (n = 0; n < 48; n += 2) {
461 | c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
462 | c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
463 | c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
464 | c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
465 | c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
466 | c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
467 | c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
468 | c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
469 | c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
470 | c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
471 |
472 | h = c8 ^ ((c2 << 1) | (c3 >>> 31));
473 | l = c9 ^ ((c3 << 1) | (c2 >>> 31));
474 | s[0] ^= h;
475 | s[1] ^= l;
476 | s[10] ^= h;
477 | s[11] ^= l;
478 | s[20] ^= h;
479 | s[21] ^= l;
480 | s[30] ^= h;
481 | s[31] ^= l;
482 | s[40] ^= h;
483 | s[41] ^= l;
484 | h = c0 ^ ((c4 << 1) | (c5 >>> 31));
485 | l = c1 ^ ((c5 << 1) | (c4 >>> 31));
486 | s[2] ^= h;
487 | s[3] ^= l;
488 | s[12] ^= h;
489 | s[13] ^= l;
490 | s[22] ^= h;
491 | s[23] ^= l;
492 | s[32] ^= h;
493 | s[33] ^= l;
494 | s[42] ^= h;
495 | s[43] ^= l;
496 | h = c2 ^ ((c6 << 1) | (c7 >>> 31));
497 | l = c3 ^ ((c7 << 1) | (c6 >>> 31));
498 | s[4] ^= h;
499 | s[5] ^= l;
500 | s[14] ^= h;
501 | s[15] ^= l;
502 | s[24] ^= h;
503 | s[25] ^= l;
504 | s[34] ^= h;
505 | s[35] ^= l;
506 | s[44] ^= h;
507 | s[45] ^= l;
508 | h = c4 ^ ((c8 << 1) | (c9 >>> 31));
509 | l = c5 ^ ((c9 << 1) | (c8 >>> 31));
510 | s[6] ^= h;
511 | s[7] ^= l;
512 | s[16] ^= h;
513 | s[17] ^= l;
514 | s[26] ^= h;
515 | s[27] ^= l;
516 | s[36] ^= h;
517 | s[37] ^= l;
518 | s[46] ^= h;
519 | s[47] ^= l;
520 | h = c6 ^ ((c0 << 1) | (c1 >>> 31));
521 | l = c7 ^ ((c1 << 1) | (c0 >>> 31));
522 | s[8] ^= h;
523 | s[9] ^= l;
524 | s[18] ^= h;
525 | s[19] ^= l;
526 | s[28] ^= h;
527 | s[29] ^= l;
528 | s[38] ^= h;
529 | s[39] ^= l;
530 | s[48] ^= h;
531 | s[49] ^= l;
532 |
533 | b0 = s[0];
534 | b1 = s[1];
535 | b32 = (s[11] << 4) | (s[10] >>> 28);
536 | b33 = (s[10] << 4) | (s[11] >>> 28);
537 | b14 = (s[20] << 3) | (s[21] >>> 29);
538 | b15 = (s[21] << 3) | (s[20] >>> 29);
539 | b46 = (s[31] << 9) | (s[30] >>> 23);
540 | b47 = (s[30] << 9) | (s[31] >>> 23);
541 | b28 = (s[40] << 18) | (s[41] >>> 14);
542 | b29 = (s[41] << 18) | (s[40] >>> 14);
543 | b20 = (s[2] << 1) | (s[3] >>> 31);
544 | b21 = (s[3] << 1) | (s[2] >>> 31);
545 | b2 = (s[13] << 12) | (s[12] >>> 20);
546 | b3 = (s[12] << 12) | (s[13] >>> 20);
547 | b34 = (s[22] << 10) | (s[23] >>> 22);
548 | b35 = (s[23] << 10) | (s[22] >>> 22);
549 | b16 = (s[33] << 13) | (s[32] >>> 19);
550 | b17 = (s[32] << 13) | (s[33] >>> 19);
551 | b48 = (s[42] << 2) | (s[43] >>> 30);
552 | b49 = (s[43] << 2) | (s[42] >>> 30);
553 | b40 = (s[5] << 30) | (s[4] >>> 2);
554 | b41 = (s[4] << 30) | (s[5] >>> 2);
555 | b22 = (s[14] << 6) | (s[15] >>> 26);
556 | b23 = (s[15] << 6) | (s[14] >>> 26);
557 | b4 = (s[25] << 11) | (s[24] >>> 21);
558 | b5 = (s[24] << 11) | (s[25] >>> 21);
559 | b36 = (s[34] << 15) | (s[35] >>> 17);
560 | b37 = (s[35] << 15) | (s[34] >>> 17);
561 | b18 = (s[45] << 29) | (s[44] >>> 3);
562 | b19 = (s[44] << 29) | (s[45] >>> 3);
563 | b10 = (s[6] << 28) | (s[7] >>> 4);
564 | b11 = (s[7] << 28) | (s[6] >>> 4);
565 | b42 = (s[17] << 23) | (s[16] >>> 9);
566 | b43 = (s[16] << 23) | (s[17] >>> 9);
567 | b24 = (s[26] << 25) | (s[27] >>> 7);
568 | b25 = (s[27] << 25) | (s[26] >>> 7);
569 | b6 = (s[36] << 21) | (s[37] >>> 11);
570 | b7 = (s[37] << 21) | (s[36] >>> 11);
571 | b38 = (s[47] << 24) | (s[46] >>> 8);
572 | b39 = (s[46] << 24) | (s[47] >>> 8);
573 | b30 = (s[8] << 27) | (s[9] >>> 5);
574 | b31 = (s[9] << 27) | (s[8] >>> 5);
575 | b12 = (s[18] << 20) | (s[19] >>> 12);
576 | b13 = (s[19] << 20) | (s[18] >>> 12);
577 | b44 = (s[29] << 7) | (s[28] >>> 25);
578 | b45 = (s[28] << 7) | (s[29] >>> 25);
579 | b26 = (s[38] << 8) | (s[39] >>> 24);
580 | b27 = (s[39] << 8) | (s[38] >>> 24);
581 | b8 = (s[48] << 14) | (s[49] >>> 18);
582 | b9 = (s[49] << 14) | (s[48] >>> 18);
583 |
584 | s[0] = b0 ^ (~b2 & b4);
585 | s[1] = b1 ^ (~b3 & b5);
586 | s[10] = b10 ^ (~b12 & b14);
587 | s[11] = b11 ^ (~b13 & b15);
588 | s[20] = b20 ^ (~b22 & b24);
589 | s[21] = b21 ^ (~b23 & b25);
590 | s[30] = b30 ^ (~b32 & b34);
591 | s[31] = b31 ^ (~b33 & b35);
592 | s[40] = b40 ^ (~b42 & b44);
593 | s[41] = b41 ^ (~b43 & b45);
594 | s[2] = b2 ^ (~b4 & b6);
595 | s[3] = b3 ^ (~b5 & b7);
596 | s[12] = b12 ^ (~b14 & b16);
597 | s[13] = b13 ^ (~b15 & b17);
598 | s[22] = b22 ^ (~b24 & b26);
599 | s[23] = b23 ^ (~b25 & b27);
600 | s[32] = b32 ^ (~b34 & b36);
601 | s[33] = b33 ^ (~b35 & b37);
602 | s[42] = b42 ^ (~b44 & b46);
603 | s[43] = b43 ^ (~b45 & b47);
604 | s[4] = b4 ^ (~b6 & b8);
605 | s[5] = b5 ^ (~b7 & b9);
606 | s[14] = b14 ^ (~b16 & b18);
607 | s[15] = b15 ^ (~b17 & b19);
608 | s[24] = b24 ^ (~b26 & b28);
609 | s[25] = b25 ^ (~b27 & b29);
610 | s[34] = b34 ^ (~b36 & b38);
611 | s[35] = b35 ^ (~b37 & b39);
612 | s[44] = b44 ^ (~b46 & b48);
613 | s[45] = b45 ^ (~b47 & b49);
614 | s[6] = b6 ^ (~b8 & b0);
615 | s[7] = b7 ^ (~b9 & b1);
616 | s[16] = b16 ^ (~b18 & b10);
617 | s[17] = b17 ^ (~b19 & b11);
618 | s[26] = b26 ^ (~b28 & b20);
619 | s[27] = b27 ^ (~b29 & b21);
620 | s[36] = b36 ^ (~b38 & b30);
621 | s[37] = b37 ^ (~b39 & b31);
622 | s[46] = b46 ^ (~b48 & b40);
623 | s[47] = b47 ^ (~b49 & b41);
624 | s[8] = b8 ^ (~b0 & b2);
625 | s[9] = b9 ^ (~b1 & b3);
626 | s[18] = b18 ^ (~b10 & b12);
627 | s[19] = b19 ^ (~b11 & b13);
628 | s[28] = b28 ^ (~b20 & b22);
629 | s[29] = b29 ^ (~b21 & b23);
630 | s[38] = b38 ^ (~b30 & b32);
631 | s[39] = b39 ^ (~b31 & b33);
632 | s[48] = b48 ^ (~b40 & b42);
633 | s[49] = b49 ^ (~b41 & b43);
634 |
635 | s[0] ^= RC[n];
636 | s[1] ^= RC[n + 1];
637 | }
638 | };
639 |
640 | module.exports = methods;
641 |
--------------------------------------------------------------------------------
/src/crypto/utils.js:
--------------------------------------------------------------------------------
1 | var jsSHA = require('jssha/src/sha256');
2 | var Blake256 = require('./blake256');
3 | var Blake224 = require('./blake224');
4 | var Blake384 = require('./blake384');
5 | var Blake512 = require('./blake512');
6 | var keccak256 = require('./sha3')['keccak256'];
7 |
8 | function numberToHex (number) {
9 | var hex = Math.round(number).toString(16);
10 | if(hex.length === 1) {
11 | hex = '0' + hex;
12 | }
13 | return hex;
14 | }
15 |
16 | module.exports = {
17 | toHex: function (arrayOfBytes) {
18 | var hex = '';
19 | for(var i = 0; i < arrayOfBytes.length; i++) {
20 | hex += numberToHex(arrayOfBytes[i]);
21 | }
22 | return hex;
23 | },
24 | sha256: function (hexString) {
25 | var sha = new jsSHA('SHA-256', 'HEX');
26 | sha.update(hexString);
27 | return sha.getHash('HEX');
28 | },
29 | sha256Checksum: function (payload) {
30 | return this.sha256(this.sha256(payload)).substr(0, 8);
31 | },
32 | blake224: function (hexString) {
33 | return new Blake224().update(hexString, 'hex').digest('hex');
34 | },
35 | blake224Checksum: function (payload) {
36 | return this.blake224(this.blake224(payload)).substr(0, 8);
37 | },
38 | blake256: function (hexString) {
39 | return new Blake256().update(hexString, 'hex').digest('hex');
40 | },
41 | blake256Checksum: function (payload) {
42 | return this.blake256(this.blake256(payload)).substr(0, 8);
43 | },
44 | blake384: function (hexString) {
45 | return new Blake384().update(hexString, 'hex').digest('hex');
46 | },
47 | blake384Checksum: function (payload) {
48 | return this.blake384(this.blake384(payload)).substr(0, 8);
49 | },
50 | blake512: function (hexString) {
51 | return new Blake512().update(hexString, 'hex').digest('hex');
52 | },
53 | blake512Checksum: function (payload) {
54 | return this.blake512(this.blake512(payload)).substr(0, 8);
55 | },
56 | keccak256: function (hexString) {
57 | return keccak256(hexString);
58 | }
59 | };
60 |
--------------------------------------------------------------------------------
/src/crypto_address_validator.js:
--------------------------------------------------------------------------------
1 | var base58 = require('./crypto/base58');
2 | var cryptoUtils = require('./crypto/utils');
3 | var currencies = require('./currencies');
4 | var IOTA = require('iota.lib.js');
5 |
6 | var DEFAULT_CURRENCY_NAME = 'bitcoin';
7 | var DEFAULT_NETWORK_TYPE = 'prod';
8 |
9 | function getDecoded(address) {
10 | try {
11 | return base58.decode(address);
12 | } catch (e) {
13 | // if decoding fails, assume invalid address
14 | return null;
15 | }
16 | }
17 |
18 | function getChecksum(hashFunction, payload) {
19 | // Each currency may implement different hashing algorithm
20 | switch (hashFunction) {
21 | case 'blake224':
22 | return cryptoUtils.blake224Checksum(payload);
23 | break;
24 | case 'blake256':
25 | return cryptoUtils.blake256Checksum(payload);
26 | break;
27 | case 'blake384':
28 | return cryptoUtils.blake384Checksum(payload);
29 | break;
30 | case 'blake512':
31 | return cryptoUtils.blake512Checksum(payload);
32 | break;
33 | case 'sha256':
34 | default:
35 | return cryptoUtils.sha256Checksum(payload);
36 | }
37 | }
38 |
39 | function getAddressType(address, currency) {
40 | currency = currency || {};
41 | // should be 25 bytes per btc address spec and 26 decred
42 | var expectedLength = currency.expectedLength || 25;
43 | var hashFunction = currency.hashFunction || 'sha256';
44 | var decoded = getDecoded(address);
45 |
46 | if (decoded) {
47 | var length = decoded.length;
48 |
49 | if (length !== expectedLength) {
50 | return null;
51 | }
52 |
53 | var checksum = cryptoUtils.toHex(decoded.slice(length - 4, length)),
54 | body = cryptoUtils.toHex(decoded.slice(0, length - 4)),
55 | goodChecksum = getChecksum(hashFunction, body);
56 |
57 | return checksum === goodChecksum ? cryptoUtils.toHex(decoded.slice(0, expectedLength - 24)) : null;
58 | }
59 |
60 | return null;
61 | }
62 |
63 | function validate(address, currencyNameOrSymbol, networkType) {
64 | currencyNameOrSymbol = currencyNameOrSymbol || DEFAULT_CURRENCY_NAME;
65 | networkType = networkType || DEFAULT_NETWORK_TYPE;
66 |
67 | var currency = currencies.getByNameOrSymbol(currencyNameOrSymbol);
68 |
69 | if (currency.validator) {
70 | return currency.validator.isValidAddress(address);
71 | }
72 |
73 | if (currency.symbol == 'xmr' || currency.symbol == 'ada') {
74 | return getDecoded(address) ? true : false;
75 | }
76 |
77 | if (currency.symbol == 'nano' || currency.symbol == 'xrb') {
78 | return address.indexOf('xrb_') > -1 ? true : false;
79 | }
80 |
81 | if (currency.symbol == 'xlm') {
82 | return (address.indexOf('G') == 0 || address.indexOf('g') == 0) && address.length == 56;
83 | }
84 |
85 | if (currency.symbol == 'nem') {
86 | return (address.indexOf('N') == 0 || address.indexOf('T') == 0 || address.indexOf('n') == 0 || address.indexOf('t') == 0) && address.length == 46;
87 | }
88 |
89 | if (currency.symbol == 'iota') {
90 | var iota = new IOTA({
91 | 'provider': null
92 | });
93 |
94 | return iota.valid.isAddress(address);
95 | }
96 |
97 | var correctAddressTypes;
98 | var addressType = getAddressType(address, currency);
99 | if (addressType == null) {
100 | return false;
101 | }
102 |
103 | if (networkType === 'prod' || networkType === 'testnet'){
104 | correctAddressTypes = currency.addressTypes[networkType]
105 | } else {
106 | correctAddressTypes = currency.addressTypes.prod.concat(currency.addressTypes.testnet);
107 | }
108 |
109 | return correctAddressTypes.indexOf(addressType) >= 0;
110 | }
111 |
112 | module.exports = {
113 | getAddressType: getAddressType,
114 | checksum: getChecksum,
115 | validate: validate,
116 | };
117 |
--------------------------------------------------------------------------------
/src/currencies.js:
--------------------------------------------------------------------------------
1 | var XRPValidator = require('./ripple_validator');
2 | var ETHValidator = require('./ethereum_validator');
3 | var NEMValidator = require('./nem_validator');
4 | var BCHValidator = require('./bch_validator');
5 |
6 | // defines P2PKH and P2SH address types for standard (prod) and testnet networks
7 | var CURRENCIES = [{
8 | name: 'bitcoin',
9 | symbol: 'btc',
10 | addressTypes: {prod: ['00', '05'], testnet: ['6f', 'c4']}
11 | },{
12 | name: 'bitcoincash',
13 | symbol: 'bch',
14 | validator: BCHValidator
15 | },{
16 | name: 'litecoin',
17 | symbol: 'ltc',
18 | addressTypes: {prod: ['30', '05', '32'], testnet: ['6f', 'c4']}
19 | },{
20 | name: 'peercoin',
21 | symbol: 'ppc',
22 | addressTypes: {prod: ['37', '75'], testnet: ['6f', 'c4']}
23 | },{
24 | name: 'dogecoin',
25 | symbol: 'doge',
26 | addressTypes: {prod: ['1e', '16'], testnet: ['71', 'c4']}
27 | },{
28 | name: 'beavercoin',
29 | symbol: 'bvc',
30 | addressTypes: {prod: ['19', '05'], testnet: ['6f', 'c4']}
31 | },{
32 | name: 'freicoin',
33 | symbol: 'frc',
34 | addressTypes: {prod: ['00', '05'], testnet: ['6f', 'c4']}
35 | },{
36 | name: 'protoshares',
37 | symbol: 'pts',
38 | addressTypes: {prod: ['38', '05'], testnet: ['6f', 'c4']}
39 | },{
40 | name: 'megacoin',
41 | symbol: 'mec',
42 | addressTypes: {prod: ['32', '05'], testnet: ['6f', 'c4']}
43 | },{
44 | name: 'primecoin',
45 | symbol: 'xpm',
46 | addressTypes: {prod: ['17', '53'], testnet: ['6f', 'c4']}
47 | },{
48 | name: 'auroracoin',
49 | symbol: 'aur',
50 | addressTypes: {prod: ['17', '05'], testnet: ['6f', 'c4']}
51 | },{
52 | name: 'namecoin',
53 | symbol: 'nmc',
54 | addressTypes: {prod: ['34'], testnet: []}
55 | },{
56 | name: 'biocoin',
57 | symbol: 'bio',
58 | addressTypes: {prod: ['19', '14'], testnet: ['6f', 'c4']}
59 | },{
60 | name: 'garlicoin',
61 | symbol: 'grlc',
62 | addressTypes: {prod: ['26', '05'], testnet: ['6f', 'c4']}
63 | },{
64 | name: 'vertcoin',
65 | symbol: 'vtc',
66 | addressTypes: {prod: ['0x', '47'], testnet: ['6f', 'c4']}
67 | },{
68 | name: 'bitcoingold',
69 | symbol: 'btg',
70 | addressTypes: {prod: ['26', '17'], testnet: ['6f', 'c4']}
71 | },{
72 | name: 'komodo',
73 | symbol: 'kmd',
74 | addressTypes: {prod: ['3c', '55'], testnet: ['0','5']}
75 | },{
76 | name: 'bitcoinz',
77 | symbol: 'btcz',
78 | expectedLength: 26,
79 | addressTypes: {prod: ['1cb8','1cbd'], testnet: ['1d25', '1cba']}
80 | },{
81 | name: 'bitcoinprivate',
82 | symbol: 'btcp',
83 | expectedLength: 26,
84 | addressTypes: {prod: ['1325','13af'], testnet: ['1957', '19e0']}
85 | },{
86 | name: 'hush',
87 | symbol: 'hush',
88 | expectedLength: 26,
89 | addressTypes: {prod: ['1cb8','1cbd'], testnet: ['1d25', '1cba']}
90 | },{
91 | name: 'snowgem',
92 | symbol: 'sng',
93 | expectedLength: 26,
94 | addressTypes: {prod: ['1c28','1c2d'], testnet: ['1d25', '1cba']}
95 | },{
96 | name: 'zcash',
97 | symbol: 'zec',
98 | expectedLength: 26,
99 | addressTypes: {prod: ['1cb8','1cbd'], testnet: ['1d25', '1cba']}
100 | },{
101 | name: 'zclassic',
102 | symbol: 'zcl',
103 | expectedLength: 26,
104 | addressTypes: {prod: ['1cb8','1cbd'], testnet: ['1d25', '1cba']}
105 | },{
106 | name: 'zencash',
107 | symbol: 'zen',
108 | expectedLength: 26,
109 | addressTypes: {prod: ['2089','2096'], testnet: ['2092','2098']}
110 | },{
111 | name: 'votecoin',
112 | symbol: 'vot',
113 | expectedLength: 26,
114 | addressTypes: {prod: ['1cb8','1cbd'], testnet: ['1d25', '1cba']}
115 | },{
116 | name: 'decred',
117 | symbol: 'dcr',
118 | addressTypes: {prod: ['073f', '071a'], testnet: ['0f21', '0efc']},
119 | hashFunction: 'blake256',
120 | expectedLength: 26
121 | },{
122 | name: 'cardano',
123 | symbol: 'ada',
124 | addressTypes: {prod: [], testnet: []},
125 | hashFunction: 'blake224',
126 | },{
127 | name: 'iota',
128 | symbol: 'iota',
129 | addressTypes: {prod: [], testnet: []},
130 | },{
131 | name: 'nano',
132 | symbol: 'nano',
133 | addressTypes: {prod: [], testnet: []},
134 | },{
135 | name: 'railblocks',
136 | symbol: 'xrb',
137 | addressTypes: {prod: [], testnet: []},
138 | },{
139 | name: 'monero',
140 | symbol: 'xmr',
141 | addressTypes: {prod: [], testnet: []},
142 | },{
143 | name: 'digibyte',
144 | symbol: 'dgb',
145 | addressTypes: {prod: ['1e'], testnet: []},
146 | },{
147 | name: 'ethereum',
148 | symbol: 'eth',
149 | validator: ETHValidator,
150 | },{
151 | name: 'etherzero',
152 | symbol: 'etz',
153 | validator: ETHValidator,
154 | },{
155 | name: 'ethereumclassic',
156 | symbol: 'etc',
157 | validator: ETHValidator,
158 | },{
159 | name: 'callisto',
160 | symbol: 'clo',
161 | validator: ETHValidator,
162 | },{
163 | name: 'icon',
164 | symbol: 'icon',
165 | validator: ETHValidator,
166 | },{
167 | name: 'eos',
168 | symbol: 'eos',
169 | validator: ETHValidator,
170 | },{
171 | name: 'qash',
172 | symbol: 'qash',
173 | validator: ETHValidator,
174 | },{
175 | name: 'republic protocol',
176 | symbol: 'ren',
177 | validator: ETHValidator,
178 | },{
179 | name: 'tronix',
180 | symbol: 'trx',
181 | validator: ETHValidator,
182 | },{
183 | name: 'vechain',
184 | symbol: 'vechain',
185 | validator: ETHValidator,
186 | },{
187 | name: 'ripple',
188 | symbol: 'xrp',
189 | validator: XRPValidator,
190 | },{
191 | name: 'stellar lumens',
192 | symbol: 'xlm',
193 | addressTypes: {prod: ['1e'], testnet: []},
194 | },{
195 | name: 'dash',
196 | symbol: 'dash',
197 | addressTypes: {prod: ['4c', '10'], testnet: ['8c', '13']}
198 | },{
199 | name: 'neo',
200 | symbol: 'neo',
201 | addressTypes: {prod: ['17'], testnet: []}
202 | },{
203 | name: 'neogas',
204 | symbol: 'gas',
205 | addressTypes: {prod: ['17'], testnet: []}
206 | },{
207 | name: 'qtum',
208 | symbol: 'qtum',
209 | addressTypes: {prod: ['3a', '32'], testnet: ['6f', 'c4']}
210 | },{
211 | name: 'nem',
212 | symbol: 'nem',
213 | validator: NEMValidator,
214 | }];
215 |
216 |
217 | module.exports = {
218 | getByNameOrSymbol: function (currencyNameOrSymbol) {
219 | var nameOrSymbol = currencyNameOrSymbol.toLowerCase();
220 | for (var i = 0; i < CURRENCIES.length; i++) {
221 | var currency = CURRENCIES[i];
222 | if(currency.name === nameOrSymbol || currency.symbol === nameOrSymbol) {
223 | return currency;
224 | }
225 | }
226 | return null;
227 | }
228 | };
229 |
--------------------------------------------------------------------------------
/src/ethereum_validator.js:
--------------------------------------------------------------------------------
1 | var cryptoUtils = require('./crypto/utils');
2 |
3 | module.exports = {
4 | isValidAddress: function (address) {
5 | if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
6 | // Check if it has the basic requirements of an address
7 | return false;
8 | }
9 |
10 | if (/^0x[0-9a-f]{40}$/.test(address) || /^0x?[0-9A-F]{40}$/.test(address)) {
11 | // If it's all small caps or all all caps, return true
12 | return true;
13 | }
14 |
15 | // Otherwise check each case
16 | return this.verifyChecksum(address);
17 | },
18 | verifyChecksum: function (address) {
19 | // Check each case
20 | address = address.replace('0x','');
21 |
22 | var addressHash = cryptoUtils.keccak256(address.toLowerCase());
23 |
24 | for (var i = 0; i < 40; i++ ) {
25 | // The nth letter should be uppercase if the nth digit of casemap is 1
26 | if ((parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) ||
27 | (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])) {
28 | return false;
29 | }
30 | }
31 |
32 | return true;
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/nem_validator.js:
--------------------------------------------------------------------------------
1 | var convert = require('./crypto/convert');
2 | var CryptoJS= require('crypto-js');
3 |
4 | const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
5 |
6 | /**
7 | * Encode a string to base32
8 | *
9 | * @param {string} s - A string
10 | *
11 | * @return {string} - The encoded string
12 | */
13 | let b32encode = function(s) {
14 | let parts = [];
15 | let quanta = Math.floor((s.length / 5));
16 | let leftover = s.length % 5;
17 |
18 | if (leftover != 0) {
19 | for (let i = 0; i < (5 - leftover); i++) {
20 | s += '\x00';
21 | }
22 | quanta += 1;
23 | }
24 |
25 | for (let i = 0; i < quanta; i++) {
26 | parts.push(alphabet.charAt(s.charCodeAt(i * 5) >> 3));
27 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5) & 0x07) << 2) | (s.charCodeAt(i * 5 + 1) >> 6)));
28 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 1) & 0x3F) >> 1)));
29 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 1) & 0x01) << 4) | (s.charCodeAt(i * 5 + 2) >> 4)));
30 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 2) & 0x0F) << 1) | (s.charCodeAt(i * 5 + 3) >> 7)));
31 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 3) & 0x7F) >> 2)));
32 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 3) & 0x03) << 3) | (s.charCodeAt(i * 5 + 4) >> 5)));
33 | parts.push(alphabet.charAt(((s.charCodeAt(i * 5 + 4) & 0x1F))));
34 | }
35 |
36 | let replace = 0;
37 | if (leftover == 1) replace = 6;
38 | else if (leftover == 2) replace = 4;
39 | else if (leftover == 3) replace = 3;
40 | else if (leftover == 4) replace = 1;
41 |
42 | for (let i = 0; i < replace; i++) parts.pop();
43 | for (let i = 0; i < replace; i++) parts.push("=");
44 |
45 | return parts.join("");
46 | }
47 |
48 | /**
49 | * Decode a base32 string.
50 | * This is made specifically for our use, deals only with proper strings
51 | *
52 | * @param {string} s - A base32 string
53 | *
54 | * @return {Uint8Array} - The decoded string
55 | */
56 | let b32decode = function(s) {
57 | let r = new ArrayBuffer(s.length * 5 / 8);
58 | let b = new Uint8Array(r);
59 | for (let j = 0; j < s.length / 8; j++) {
60 | let v = [0, 0, 0, 0, 0, 0, 0, 0];
61 | for (let i = 0; i < 8; ++i) {
62 | v[i] = alphabet.indexOf(s[j * 8 + i]);
63 | }
64 | let i = 0;
65 | b[j * 5 + 0] = (v[i + 0] << 3) | (v[i + 1] >> 2);
66 | b[j * 5 + 1] = ((v[i + 1] & 0x3) << 6) | (v[i + 2] << 1) | (v[i + 3] >> 4);
67 | b[j * 5 + 2] = ((v[i + 3] & 0xf) << 4) | (v[i + 4] >> 1);
68 | b[j * 5 + 3] = ((v[i + 4] & 0x1) << 7) | (v[i + 5] << 2) | (v[i + 6] >> 3);
69 | b[j * 5 + 4] = ((v[i + 6] & 0x7) << 5) | (v[i + 7]);
70 | }
71 | return b;
72 | }
73 |
74 | /**
75 | * Convert a public key to a NEM address
76 | *
77 | * @param {string} publicKey - A public key
78 | * @param {number} networkId - A network id
79 | *
80 | * @return {string} - The NEM address
81 | */
82 | let toAddress = function(publicKey, networkId) {
83 | let binPubKey = CryptoJS.enc.Hex.parse(publicKey);
84 | let hash = CryptoJS.SHA3(binPubKey, {
85 | outputLength: 256
86 | });
87 | let hash2 = CryptoJS.RIPEMD160(hash);
88 | // 98 is for testnet
89 | let networkPrefix = Network.id2Prefix(networkId);
90 | let versionPrefixedRipemd160Hash = networkPrefix + CryptoJS.enc.Hex.stringify(hash2);
91 | let tempHash = CryptoJS.SHA3(CryptoJS.enc.Hex.parse(versionPrefixedRipemd160Hash), {
92 | outputLength: 256
93 | });
94 | let stepThreeChecksum = CryptoJS.enc.Hex.stringify(tempHash).substr(0, 8);
95 | let concatStepThreeAndStepSix = convert.hex2a(versionPrefixedRipemd160Hash + stepThreeChecksum);
96 | let ret = b32encode(concatStepThreeAndStepSix);
97 | return ret;
98 | };
99 |
100 | /**
101 | * Check if an address is from a specified network
102 | *
103 | * @param {string} _address - An address
104 | * @param {number} networkId - A network id
105 | *
106 | * @return {boolean} - True if address is from network, false otherwise
107 | */
108 | let isFromNetwork = function(_address, networkId) {
109 | let address = _address.toString().toUpperCase().replace(/-/g, '');
110 | let a = address[0];
111 | return Network.id2Char(networkId) === a;
112 | };
113 |
114 | /**
115 | * Check if an address is valid
116 | *
117 | * @param {string} _address - An address
118 | *
119 | * @return {boolean} - True if address is valid, false otherwise
120 | */
121 | let isValidAddress = function(_address) {
122 | let address = _address.toString().toUpperCase().replace(/-/g, '');
123 | if (!address || address.length !== 40) {
124 | return false;
125 | }
126 | let decoded = convert.ua2hex(b32decode(address));
127 | let versionPrefixedRipemd160Hash = CryptoJS.enc.Hex.parse(decoded.slice(0, 42));
128 | let tempHash = CryptoJS.SHA3(versionPrefixedRipemd160Hash, {
129 | outputLength: 256
130 | });
131 | let stepThreeChecksum = CryptoJS.enc.Hex.stringify(tempHash).substr(0, 8);
132 |
133 | return stepThreeChecksum === decoded.slice(42);
134 | };
135 |
136 | /**
137 | * Remove hyphens from an address
138 | *
139 | * @param {string} _address - An address
140 | *
141 | * @return {string} - A clean address
142 | */
143 | let clean = function(_address) {
144 | return _address.toUpperCase().replace(/-|\s/g,"");
145 | };
146 |
147 | module.exports = {
148 | b32encode,
149 | b32decode,
150 | toAddress,
151 | isFromNetwork,
152 | isValidAddress,
153 | clean
154 | }
--------------------------------------------------------------------------------
/src/ripple_validator.js:
--------------------------------------------------------------------------------
1 | var cryptoUtils = require('./crypto/utils');
2 | var baseX = require('base-x');
3 |
4 | var ALLOWED_CHARS = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz';
5 |
6 | var codec = baseX(ALLOWED_CHARS);
7 | var regexp = new RegExp('^r[' + ALLOWED_CHARS + ']{27,35}$');
8 |
9 | module.exports = {
10 | /**
11 | * ripple address validation
12 | */
13 | isValidAddress: function (address) {
14 | if (regexp.test(address)) {
15 | return this.verifyChecksum(address);
16 | }
17 |
18 | return false;
19 | },
20 |
21 | verifyChecksum: function (address) {
22 | var bytes = codec.decode(address);
23 | var computedChecksum = cryptoUtils.sha256Checksum(cryptoUtils.toHex(bytes.slice(0, -4)));
24 | var checksum = cryptoUtils.toHex(bytes.slice(-4));
25 |
26 | return computedChecksum === checksum
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/test/crypto_address_validator.js:
--------------------------------------------------------------------------------
1 | var isNode = typeof module !== 'undefined' && typeof module.exports !== 'undefined';
2 |
3 | var chai = isNode ? require('chai') : window.chai,
4 | expect = chai.expect;
5 |
6 | var CAValidator = isNode ? require('../src/crypto_address_validator') : window.CAValidator;
7 |
8 | function valid (address, currency, networkType) {
9 | var result = CAValidator.validate(address, currency, networkType);
10 | // console.log(result)
11 | expect(result).to.be.true;
12 | }
13 |
14 | function invalid (address, currency, networkType) {
15 | var result = CAValidator.validate(address, currency, networkType);
16 | expect(result).to.be.false;
17 | }
18 |
19 | describe('CAValidator.validate()', function () {
20 | describe('valid results', function () {
21 | it('should return true for correct bitcoin addresses', function () {
22 | valid('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP', 'bitcoin');
23 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bitcoin');
24 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'BTC');
25 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'Bitcoin');
26 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'btc');
27 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'btc', 'prod');
28 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'btc', 'both');
29 | valid('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', 'bitcoin');
30 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoin', 'testnet');
31 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoin', 'both');
32 |
33 | valid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez');
34 | valid('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd');
35 |
36 | // p2sh addresses
37 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt');
38 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'bitcoin');
39 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'bitcoin', 'testnet');
40 | });
41 |
42 | it('should return true for correct bitcoincash addresses', function () {
43 | valid('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP', 'bitcoincash');
44 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bitcoincash');
45 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'BCH');
46 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'Bitcoin');
47 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bch');
48 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bch', 'prod');
49 | valid('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y', 'bch', 'both');
50 | valid('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', 'bitcoincash');
51 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoincash', 'testnet');
52 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'bitcoincash', 'both');
53 |
54 | // p2sh addresses
55 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'bitcoincash');
56 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'bitcoincash', 'testnet');
57 | });
58 |
59 | it('should return true for correct litecoin addresses', function () {
60 | valid('LVg2kJoFNg45Nbpy53h7Fe1wKyeXVRhMH9', 'litecoin');
61 | valid('LVg2kJoFNg45Nbpy53h7Fe1wKyeXVRhMH9', 'LTC');
62 | valid('LTpYZG19YmfvY2bBDYtCKpunVRw7nVgRHW', 'litecoin');
63 | valid('Lb6wDP2kHGyWC7vrZuZAgV7V4ECyDdH7a6', 'litecoin');
64 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'litecoin', 'testnet');
65 |
66 | // p2sh addresses
67 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'litecoin');
68 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'litecoin', 'testnet');
69 | });
70 |
71 | it('should return true for correct peercoin addresses', function () {
72 | valid('PHCEsP6od3WJ8K2WKWEDBYKhH95pc9kiZN', 'peercoin');
73 | valid('PSbM1pGoE9dnAuVWvpQqTTYVpKZU41dNAz', 'peercoin');
74 | valid('PUULeHrJL2WujJkorc2RsUAR3SardKUauu', 'peercoin');
75 | valid('PUULeHrJL2WujJkorc2RsUAR3SardKUauu', 'PPC');
76 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'peercoin', 'testnet');
77 |
78 | // p2sh addresses
79 | valid('pNms4CaWqgZUxbNZaA1yP2gPr3BYnez9EM', 'peercoin');
80 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'peercoin', 'testnet');
81 | });
82 |
83 | it('should return true for correct dogecoin addresses', function () {
84 | valid('DPpJVPpvPNP6i6tMj4rTycAGh8wReTqaSU', 'dogecoin');
85 | valid('DNzLUN6MyYVS5zf4Xc2yK69V3dXs6Mxia5', 'dogecoin');
86 | valid('DPS6iZj7roHquvwRYXNBua9QtKPzigUUhM', 'dogecoin');
87 | valid('DPS6iZj7roHquvwRYXNBua9QtKPzigUUhM', 'DOGE');
88 | //TODO: NEED A DOGECOIN TESTNET ADDRESS
89 |
90 | //p2sh addresses
91 | valid('A7JjzK9k9x5b2MkkQzqt91WZsuu7wTu6iS', 'dogecoin');
92 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'dogecoin', 'testnet');
93 | });
94 |
95 | it('should return true for correct beavercoin addresses', function () {
96 | valid('BPPtB4EpPi5wCaGXZuNyKQgng8ya579qUh', 'beavercoin');
97 | valid('BC1LLYoE4mTCHTJhVYvLGxhRTwAHyWTQ49', 'beavercoin');
98 | valid('BBuyeg2vjtyFdMNj3LTxuVra4wJMKVAY9C', 'beavercoin');
99 | valid('BBuyeg2vjtyFdMNj3LTxuVra4wJMKVAY9C', 'BVC');
100 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'beavercoin', 'testnet');
101 |
102 | // p2sh addresses
103 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'beavercoin');
104 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'beavercoin', 'testnet');
105 | });
106 |
107 | it('should return true for correct litecoin freicoin', function () {
108 | valid('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'freicoin');
109 | valid('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs', 'freicoin');
110 | valid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez', 'freicoin');
111 | valid('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez', 'FRC');
112 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'freicoin', 'testnet');
113 |
114 | // p2sh addresse
115 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'freicoin');
116 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'freicoin', 'testnet');
117 | });
118 |
119 | it('should return true for correct protoshares addresses', function () {
120 | valid('PaNGELmZgzRQCKeEKM6ifgTqNkC4ceiAWw', 'protoshares');
121 | valid('Piev8TMX2fT5mFtgxx2TXJaqXP37weMPuD', 'protoshares');
122 | valid('PgsuLoe9ojRKFGJGVpqqk37gAqNJ4ozboD', 'protoshares');
123 | valid('PgsuLoe9ojRKFGJGVpqqk37gAqNJ4ozboD', 'PTS');
124 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'protoshares', 'testnet');
125 |
126 | //p2sh addresses
127 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'protoshares');
128 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'protoshares', 'testnet');
129 | });
130 |
131 | it('should return true for correct megacoin addresses', function () {
132 | valid('MWUHaNxjXGZUYTh92i3zuDmsnH1rHSBk5M', 'megacoin');
133 | valid('MSAkrhRyte7bz999Ga5SqYjzypFFYa2oEb', 'megacoin');
134 | valid('MLUTAtDQFcfo1QACWocLuufFq5fBDTpCHE', 'megacoin');
135 | valid('MLUTAtDQFcfo1QACWocLuufFq5fBDTpCHE', 'MEC');
136 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'megacoin', 'testnet');
137 |
138 | //p2sh addresses
139 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'megacoin');
140 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'megacoin', 'testnet');
141 | });
142 |
143 | it('should return true for correct primecoin addresses', function () {
144 | valid('AVKeiZ5JadfWdH2EYVgVRfX4ufoyd4ehuM', 'primecoin');
145 | valid('AQXBRPyob4dywUJ21RUKrR1xetQCDVenKD', 'primecoin');
146 | valid('ANHfTZnskKqaBU7oZuSha9SpbHU3YBfeKf', 'primecoin');
147 | valid('AYdiYMKSGYxLcZNDmqB8jNcck7SQibrfiK', 'primecoin');
148 | valid('AYdiYMKSGYxLcZNDmqB8jNcck7SQibrfiK', 'XPM');
149 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'primecoin', 'testnet');
150 |
151 | //p2sh addresses
152 | valid('af5CvTQq7agDh717Wszb5QDbWb7nT2mukP', 'primecoin');
153 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'primecoin', 'testnet');
154 | });
155 |
156 | it('should return true for correct auroracoin addresses', function () {
157 | valid('ARM3GLZXF1PDTZ5vz3wh5MVahbK9BHTWAN', 'auroracoin');
158 | valid('AUtfc6ThCLb7FuEu7QPrWpJuaXaJRPciDF', 'auroracoin');
159 | valid('AUN1oaj5hjispGnczt8Aruw3TxgGyRqB3V', 'auroracoin');
160 | valid('AXGcBkGX6NiaDXj85C5dCrhTRUgwxSkKDK', 'auroracoin');
161 | valid('AXGcBkGX6NiaDXj85C5dCrhTRUgwxSkKDK', 'AUR');
162 | valid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'auroracoin', 'testnet');
163 |
164 | //p2sh addresses
165 | valid('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'auroracoin');
166 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'auroracoin', 'testnet');
167 | });
168 |
169 | it('should return true for correct namecoin addresses', function () {
170 | valid('NEpeRmS775fnti8TDgJA28m8KLEfNNRZvT', 'namecoin');
171 | valid('MyJ691bGJ48RBK2LS8n1U57wcFLFScFXxi', 'namecoin');
172 | valid('NFY9aw1RXLGtWpeqgNQXprnUcZXyKNinTh', 'namecoin');
173 | valid('NCPPc7Pzb75CpRPJQPRRh6ouJTq7BCy1H4', 'namecoin');
174 | valid('NCPPc7Pzb75CpRPJQPRRh6ouJTq7BCy1H4', 'NMC');
175 | });
176 |
177 | it('should return true for correct BioCoin addresses', function () {
178 | valid('B7xseoLGk7hEpMDDeSvZDKmmiAMHWiccok', 'biocoin');
179 | valid('B8zjmYFGhWmiaQSJshfrnefE72xCapCkvo', 'biocoin');
180 | valid('muH8LL42DiMs8GEQ6Grfi8KUw2uFvuKr1J', 'biocoin', 'testnet');
181 | valid('muH8LL42DiMs8GEQ6Grfi8KUw2uFvuKr1J', 'BIO', 'testnet');
182 | valid('B8zjmYFGhWmiaQSJshfrnefE72xCapCkvo', 'BIO');
183 | });
184 |
185 | it('should return true for correct Garlicoin addresses', function () {
186 | valid('GU2NtcNotWFiZjTp2Vdgf5CjeMfgsWYCua', 'garlicoin');
187 | valid('GNWeWaoQ6rv21ZFjJWT9vb91hXUzFTLkru', 'garlicoin');
188 | valid('mjKbQTkgwzmsL3J86tdVzhyW9pc4NePqTb', 'garlicoin', 'testnet');
189 | valid('mnYp36NuyRavMKQ9Q9Q6oGqoorAs9p3zYn', 'GRLC', 'testnet');
190 | valid('GU2NtcNotWFiZjTp2Vdgf5CjeMfgsWYCua', 'GRLC');
191 | });
192 |
193 | it('should return true for correct Vertcoin addresses', function () {
194 | valid('VmoMjGf3zgZLy8sk3PMKd3xikZHXWvnYi7', 'vertcoin');
195 | valid('VmhHwXr3J8xMZpy62WuBGpu3xVvThWzcTQ', 'vertcoin');
196 | valid('mvww6DEJ18dbyQUukpVQXvLgrNDJazZn1Y', 'vertcoin', 'testnet');
197 | valid('mn3mdEE6cf1snxVsknNz4GRTdSrWXqYp7c', 'VTC', 'testnet');
198 | valid('Vri6Q4GgNFfdtcpxD961TotJwaSaYQCaL5', 'VTC');
199 | });
200 |
201 | it('should return true for correct BitcoinGold addresses', function () {
202 | valid('GW3JrQyHtoVfEFES3Y9JagiX3VSKQStLwj', 'bitcoingold');
203 | valid('GUDWdeMyAXQbrNFFivAhkJQ1GfBCFdc7JF', 'bitcoingold');
204 | valid('mvww6DEJ18dbyQUukpVQXvLgrNDJazZn1Y', 'bitcoingold', 'testnet');
205 | valid('mn3mdEE6cf1snxVsknNz4GRTdSrWXqYp7c', 'BTG', 'testnet');
206 | valid('GSNFPRsdaM3MXrU5HW1AxgFwmUQC8HXK9F', 'BTG');
207 | });
208 |
209 | it('should return true for correct Decred addresses', function () {
210 | valid('Dsesax2GJnMN4wwmWo5rJGq73dDK217Rh85', 'DCR');
211 | valid('DsYuxtvGRfN8rncXAndtLUpJm55F77K17RA', 'decred');
212 | valid('DsaXDG2NrJW8g4tFAb8n9MNx81Sn3Qc8AEV', 'decred');
213 | valid('TsijUgejaRnLKF5WAbpUxNtwKGUiKVeXLr7', 'decred', 'testnet');
214 | valid('TsZ9QmAoadF12hGvyALp6qvaF4be3BmLqG9', 'dcr', 'testnet');
215 | });
216 |
217 | it('should return true for correct Digibyte addresses', function () {
218 | valid('DG2rM2orU2JH5i4ACh3AKNpRTNESdv5xf8', 'DGB');
219 | valid('DBR2Lj1F17eHGHXgbpae2Wb4m39bDyA1qo', 'DGB');
220 | valid('D9TDZTR9Z9Mx2NoDJnhqhnYhDLKRAmsL9n', 'digibyte');
221 | valid('DHRzA1YHA1kFWpz2apRckZJy6KZRyGq4EV', 'digibyte');
222 | valid('DJ53hTyLBdZp2wMi5BsCS3rtEL1ioYUkva', 'digibyte');
223 | });
224 |
225 | it('should return true for correct Ethereum addresses', function () {
226 | valid('0xE37c0D48d68da5c5b14E5c1a9f1CFE802776D9FF', 'ethereum');
227 | valid('0xa00354276d2fC74ee91e37D085d35748613f4748', 'ethereum');
228 | valid('0xAff4d6793F584a473348EbA058deb8caad77a288', 'ETH');
229 | valid('0xc6d9d2cd449a754c494264e1809c50e34d64562b', 'ETH');
230 | valid('0x52908400098527886E0F7030069857D2E4169EE7', 'ETH');
231 | valid('0x8617E340B3D01FA5F11F306F4090FD50E238070D', 'ETH');
232 | valid('0xde709f2102306220921060314715629080e2fb77', 'ETH');
233 | valid('0x27b1fdb04752bbc536007a920d24acb045561c26', 'ETH');
234 | valid('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed', 'ETH');
235 | valid('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359', 'ETH');
236 | valid('0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB', 'ETH');
237 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ETH');
238 |
239 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ethereumclassic');
240 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ETC');
241 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'etherzero');
242 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'ETZ');
243 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'callisto');
244 | valid('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb', 'CLO');
245 | });
246 |
247 | it('should return true for correct Ripple addresses', function () {
248 | valid('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn', 'ripple');
249 | valid('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn', 'XRP');
250 | valid('r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV', 'XRP');
251 | valid('rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', 'XRP');
252 | valid('rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN', 'XRP');
253 | });
254 |
255 | it('should return true for correct dash addresses', function () {
256 | valid('Xx4dYKgz3Zcv6kheaqog3fynaKWjbahb6b', 'dash');
257 | valid('XcY4WJ6Z2Q8w7vcYER1JypC8s2oa3SQ1b1', 'DASH');
258 | valid('XqMkVUZnqe3w4xvgdZRtZoe7gMitDudGs4', 'dash');
259 | valid('yPv7h2i8v3dJjfSH4L3x91JSJszjdbsJJA', 'dash', 'testnet');
260 | });
261 |
262 | it('should return true for correct neo addresses', function () {
263 | valid('AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTT', 'neo');
264 | valid('AKDVzYGLczmykdtRaejgvWeZrvdkVEvQ1X', 'NEO');
265 | });
266 |
267 | it('should return true for correct neo gas addresses', function () {
268 | valid('AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTT', 'neogas');
269 | });
270 |
271 | it('should return true for correct qtum addresses', function () {
272 | valid('QNjUiD3bVVZwYTc5AhpeQbS1mfb2guyWhe', 'qtum');
273 | valid('QVZnSrMwKp6AL4FjUPPnfFgsma6j1DXQXu', 'QTUM');
274 | valid('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'qtum', 'testnet');
275 | });
276 |
277 | it('should return true for correct votecoin addresses', function () {
278 | valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'votecoin');
279 | valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'VOT');
280 | valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'votecoin', 'testnet');
281 | });
282 |
283 | it('should return true for correct bitcoinz addresses', function () {
284 | valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'bitcoinz');
285 | valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'BTCZ');
286 | valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'bitcoinz', 'testnet');
287 | });
288 |
289 | it('should return true for correct zclassic addresses', function () {
290 | valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zclassic');
291 | valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZCL');
292 | valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zclassic', 'testnet');
293 | });
294 |
295 | it('should return true for correct hush addresses', function () {
296 | valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'hush');
297 | valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'HUSH');
298 | valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'hush', 'testnet');
299 | });
300 |
301 | it('should return true for correct zcash addresses', function () {
302 | valid('t1U9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zcash');
303 | valid('t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZEC');
304 | valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zcash', 'testnet');
305 | });
306 |
307 | it('should return true for correct bitcoinprivate addresses', function () {
308 | valid('b1M4XXPFhwMb1SP33yhzn3h9qWXjujkgep4', 'bitcoinprivate');
309 | //valid('bx....', 'BTCP');
310 | //valid('nx....', 'bitcoinprivate', 'testnet');
311 | });
312 |
313 | it('should return true for correct snowgem addresses', function () {
314 | valid('s1fx7WBkjB4UH6qQjPp6Ysmtr1C1JiTK2Yw', 'snowgem');
315 | valid('s3d27MhkBRt3ha2UuxhjXaYF4DCnttTMnL1', 'SNG');
316 | valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'snowgem', 'testnet');
317 | });
318 |
319 | it('should return true for correct zencash addresses', function () {
320 | valid('znhiGGfYRepxkBjXYvA2kFrXiC351i9ta4z', 'zencash');
321 | valid('zssEdGnZCQ9G86LZFtbynMn1hYTVhn6eYCL', 'ZEN');
322 | valid('ztmWMDLWjbruCJxKmmfAZiT6QAQdiv5F291', 'zencash', 'testnet');
323 | });
324 |
325 | it('should return true for correct komodo addresses', function () {
326 | valid('R9R5HirAzqDcWrWGiJEL115dpV3QB3hobH', 'komodo');
327 | valid('RAvj2KKVUohTu3hVdNJ4U6hQi7TNawpacH', 'KMD');
328 | //valid('t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'komodo', 'testnet');
329 | });
330 |
331 | it('should return true for correct cardano addresses', function () {
332 | valid('DdzFFzCqrhshnNGrGXPycCp9hhjREgs1UGrq5u43LQk6SBrNc6SxEAStAuWrJDostnpfaY2XakBjSCrutcSCrhrAcFCEFAH8DnWSEe8n', 'cardano');
333 | valid('4swhHtxKapQbj3TZEipgtp7NQzcRWDYqCxXYoPQWjGyHmhxS1w1TjUEszCQT1sQucGwmPQMYdv1FYs3d51KgoubviPBf', 'ada');
334 | });
335 |
336 | it('should return true for correct monero addresses', function () {
337 | valid('44WyHZouRYSGHm7o7y8Dig2h3R9F1Q8g1ctXAwHZ3k2J1rSRXshAHguDBxGe9hAK882CLWRvW7e14hbbH3jYewwWDDxAPbr', 'monero');
338 | valid('49bcHjtoqf5EZpRRv56CwQPMeQ8d6bVwKZMhUyieUPrQFydoDHvpTfRfWsCM6r1BgeTxQkSXAHWewL49ArLEWD6c1Y2mfHk', 'xmr');
339 | });
340 |
341 | it('should return true for correct icon addresses', function () {
342 | valid('0x03747f06215b44e498831da019b27f53e483599f', 'icon');
343 | valid('0xd60a63fa71685d54a4c7cb8a7f7d1823164a62b1', 'icon');
344 | });
345 |
346 | it('should return true for correct nano or raiblocks addresses', function () {
347 | valid('xrb_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs', 'nano');
348 | valid(' xrb_3pczxuorp48td8645bs3m6c3xotxd3idskrenmi65rbrga5zmkemzhwkaznh', 'railblocks');
349 | valid(' xrb_1q79ahdr36uqn38p5tp5sqwkn73rnpj1k8obtuetdbjcx37d5gahhd1u9cuh', 'xrb');
350 | });
351 |
352 | it('should return true for correct iota addresses', function () {
353 | valid('QY9XJUVWHY9ILWONEJLENLLETRKFELNVUOUXCTDDDLQSVXHLGDEPMMJPZROKNJSQQVNDPABCCIOZBQJTZ', 'iota');
354 | valid('YVGZVANHSLUBSVNUBJMQCHCGYW9ZXTDBZHSVRND9RIZLQHMDGEYMDHLAMTOKPEKDIFOP9BND9QMIKFHSADKJTSBTTX', 'iota');
355 | });
356 |
357 | it('should return true for correct eos addresses', function () {
358 | valid('0xc29dc7d7c8557f4f688E8dF1A32F7330ad02f542', 'eos');
359 | valid('0x90A6CAecdf88Cb7670457EDd9413e239708FAc50', 'eos');
360 | });
361 |
362 | it('should return true for correct qash addresses', function () {
363 | valid('0xe9830ddfd1da3fc5dbea1957d97cdb5092c271f2', 'qash');
364 | valid('0x3ed15ca2279a2a73000fa9c0998b811a9569a0aa', 'qash');
365 | });
366 |
367 | it('should return true for correct tronix addresses', function () {
368 | valid('0x46705dfff24256421a05d056c29e81bdc09723b8', 'tronix');
369 | valid('0x05ee4cd61f8c7b83d4d310fe80dda49ffa9ba164', 'trx');
370 | });
371 |
372 | it('should return true for correct nem addresses', function () {
373 | valid('TBU3ZK-HU6WRY-YXE6LQ-YC6WIO-IXTAVW-WNQK2L-QH2A', 'nem');
374 | valid('nb7uva-jkdefp-zja6ff-zwggw3-fk2m7o-ee3uqb-y7qm', 'nem');
375 | });
376 |
377 | it('should return true for correct vechain addresses', function () {
378 | valid('0xd551234ae421e3bcba99a0da6d736074f22192ff', 'vechain');
379 | });
380 |
381 | it('should return true for correct republic protocol addresses', function () {
382 | valid('0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208', 'republic protocol');
383 | valid('0x6a188cfb207f987526a62a2368695443512159ae', 'ren');
384 | });
385 |
386 | it('should return true for correct stellar lumens addresses', function () {
387 | valid('GDSSTV4HQ4NV5MUNH2LX7Q5MUAGH7KV64PUWTMODPA6JGGJLVKNGY2HP', 'stellar lumens');
388 | valid('GBH4TZYZ4IRCPO44CBOLFUHULU2WGALXTAVESQA6432MBJMABBB4GIYI', 'xlm');
389 | });
390 | });
391 |
392 | describe('invalid results', function () {
393 | function commonTests(currency) {
394 | invalid('', currency); //reject blank
395 | invalid('%%@', currency); //reject invalid base58 string
396 | invalid('1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa', currency); //reject invalid address
397 | invalid('bd839e4f6fadb293ba580df5dea7814399989983', currency); //reject transaction id's
398 | //testnet
399 | invalid('', currency, 'testnet'); //reject blank
400 | invalid('%%@', currency, 'testnet'); //reject invalid base58 string
401 | invalid('1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa', currency, 'testnet'); //reject invalid address
402 | invalid('bd839e4f6fadb293ba580df5dea7814399989983', currency, 'testnet'); //reject transaction id's
403 | }
404 |
405 | it('should return false for incorrect bitcoin addresses', function () {
406 | commonTests('bitcoin');
407 | });
408 |
409 | it('should return false for incorrect bitcoincash addresses', function () {
410 | commonTests('bitcoincash');
411 | });
412 |
413 | it('should return false for incorrect litecoin addresses', function () {
414 | commonTests('litecoin');
415 | });
416 |
417 | it('should return false for incorrect peercoin addresses', function () {
418 | commonTests('peercoin');
419 | });
420 |
421 | it('should return false for incorrect dogecoin addresses', function () {
422 | commonTests('dogecoin');
423 | });
424 |
425 | it('should return false for incorrect beavercoin addresses', function () {
426 | commonTests('beavercoin');
427 | });
428 |
429 | it('should return false for incorrect freicoin addresses', function () {
430 | commonTests('freicoin');
431 | });
432 |
433 | it('should return false for incorrect protoshares addresses', function () {
434 | commonTests('protoshares');
435 | });
436 |
437 | it('should return false for incorrect megacoin addresses', function () {
438 | commonTests('megacoin');
439 | });
440 |
441 | it('should return false for incorrect primecoin addresses', function () {
442 | commonTests('primecoin');
443 | });
444 |
445 | it('should return false for incorrect auroracoin addresses', function () {
446 | commonTests('auroracoin');
447 | });
448 |
449 | it('should return false for incorrect namecoin addresses', function () {
450 | commonTests('namecoin');
451 | });
452 |
453 | it('should return false for incorrect biocoin addresses', function () {
454 | commonTests('biocoin');
455 | });
456 |
457 | it('should return false for incorrect garlicoin addresses', function () {
458 | commonTests('garlicoin');
459 | });
460 |
461 | it('should return false for incorrect vertcoin addresses', function () {
462 | commonTests('vertcoin');
463 | });
464 |
465 | it('should return false for incorrect bitcoingold addresses', function () {
466 | commonTests('bitcoingold');
467 | });
468 |
469 | it('should return false for incorrect decred addresses', function () {
470 | commonTests('decred');
471 | });
472 |
473 | it('should return false for incorrect digibyte addresses', function () {
474 | commonTests('digibyte');
475 | });
476 |
477 | it('should return false for incorrect nano or railblocks addresses', function () {
478 | commonTests('nano');
479 | });
480 |
481 | it('should return false for incorrect nem addresses', function () {
482 | commonTests('nem');
483 | });
484 |
485 | it('should return false for incorrect iota addresses', function () {
486 | commonTests('iota');
487 | });
488 |
489 | it('should return false for incorrect stellar lumens addresses', function () {
490 | commonTests('xlm');
491 | });
492 |
493 | it('should return false for incorrect cardano addresses', function () {
494 | invalid('0xAff4d6793F584a473348EbA058deb8caad77a288', 'cardano');
495 | });
496 |
497 | it('should return false for incorrect monero addresses', function () {
498 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'monero');
499 | });
500 |
501 | it('should return false for incorrect eip55 addresses', function () {
502 | invalid('6xAff4d6793F584a473348EbA058deb8caad77a288', 'ethereum');
503 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'ethereum');
504 | invalid('0XD1220A0CF47C7B9BE7A2E6BA89F429762E7B9ADB', 'ethereum');
505 | invalid('aFf4d6793f584a473348ebA058deb8caad77a2885', 'ethereum');
506 | invalid('0xff4d6793F584a473', 'ethereum');
507 |
508 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'ethereumclassic');
509 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'etherzero');
510 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'callisto');
511 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'icon');
512 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'eos');
513 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'qash');
514 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'ren');
515 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'trx');
516 | invalid('0x02fcd51aAbB814FfFe17908fbc888A8975D839A5', 'vechain');
517 | });
518 |
519 | it('should return false for incorrect ripple addresses', function () {
520 | invalid('rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCN', 'ripple');
521 | invalid('rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhMN', 'XRP');
522 | invalid('6xAff4d6793F584a473348EbA058deb8ca', 'ripple');
523 | invalid('DJ53hTyLBdZp2wMi5BsCS3rtEL1ioYUkva', 'ripple');
524 | });
525 |
526 | it('should return false for incorrect dash addresses', function () {
527 | commonTests('dash');
528 | });
529 |
530 | it('should return false for incorrect neo addresses', function () {
531 | commonTests('neo');
532 | invalid('AR4QmqYENiZAD6oXe7ftm6eDcwtHk7rVTa', 'neo');
533 | invalid('AKDVzYGLczmykdtRaejgvWeZrvdkVEvQ10', 'NEO');
534 | });
535 |
536 | it('should return false for incorrect qtum addresses', function () {
537 | commonTests('qtum');
538 | invalid('QNPhBbVhDghASxcUh2vHotQUgNeLRFTcfb', 'qtum');
539 | invalid('QOPhBbVhDghASxcUh2vHotQUgNeLRFTcfa', 'QTUM');
540 | });
541 |
542 | it('should return false for incorrect votecoin addresses', function () {
543 | commonTests('votecoin');
544 | invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'votecoin');
545 | invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'VOT');
546 | invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'votecoin', 'testnet');
547 | });
548 |
549 | it('should return false for incorrect bitcoinz addresses', function () {
550 | commonTests('bitcoinz');
551 | invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'bitcoinz');
552 | invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'BTCZ');
553 | invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'bitcoinz', 'testnet');
554 | });
555 |
556 | it('should return false for incorrect zclassic addresses', function () {
557 | commonTests('zclassic');
558 | invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zclassic');
559 | invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZCL');
560 | invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zclassic', 'testnet');
561 | });
562 |
563 | it('should return false for incorrect hush addresses', function () {
564 | invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'hush');
565 | invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'HUSH');
566 | invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'hush', 'testnet');
567 | });
568 |
569 | it('should return false for incorrect zcash addresses', function () {
570 | commonTests('zcash');
571 | invalid('t1Y9yhDa5XEjgfnTgZoKddeSiEN1aoLkQxq', 'zcash');
572 | invalid('t3Yz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd', 'ZEC');
573 | invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'zcash', 'testnet');
574 | });
575 |
576 | it('should return false for incorrect bitcoinprivate addresses', function () {
577 | commonTests('bitcoinprivate');
578 | invalid('b1Y4XXPFhwMb1SP33yhzn3h9qWXjujkgep4', 'bitcoinprivate');
579 | //invalid('bx....', 'BTCP');
580 | //invalid('nx....', 'bitcoinprivate', 'testnet');
581 | });
582 |
583 | it('should return false for incorrect snowgem addresses', function () {
584 | commonTests('snowgem');
585 | invalid('s1Yx7WBkjB4UH6qQjPp6Ysmtr1C1JiTK2Yw', 'snowgem');
586 | invalid('s3Y27MhkBRt3ha2UuxhjXaYF4DCnttTMnL1', 'SNG');
587 | invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'snowgem', 'testnet');
588 | });
589 |
590 | it('should return false for incorrect zencash addresses', function () {
591 | commonTests('zencash');
592 | invalid('znYiGGfYRepxkBjXYvA2kFrXiC351i9ta4z', 'zencash');
593 | invalid('zsYEdGnZCQ9G86LZFtbynMn1hYTVhn6eYCL', 'ZEN');
594 | invalid('ztYWMDLWjbruCJxKmmfAZiT6QAQdiv5F291', 'zencash', 'testnet');
595 | });
596 |
597 | it('should return false for incorrect komodo addresses', function () {
598 | commonTests('komodo');
599 | invalid('R9Y5HirAzqDcWrWGiJEL115dpV3QB3hobH', 'komodo');
600 | invalid('RAYj2KKVUohTu3hVdNJ4U6hQi7TNawpacH', 'KMD');
601 | //invalid('t2YNzUUx8mWBCRYPRezvA363EYXyEpHokyi', 'komodo', 'testnet');
602 | });
603 |
604 | });
605 | });
606 |
--------------------------------------------------------------------------------