├── .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 | --------------------------------------------------------------------------------