jwallet-web-keystore
Advanced tools
Comparing version
{ | ||
"name": "jwallet-web-keystore", | ||
"version": "0.3.2", | ||
"version": "0.4.0", | ||
"description": "Library for ethereum blockchain accounts management", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -421,12 +421,11 @@ # jwallet-web-keystore | ||
#### isHexStringValid(hex, hexLength) | ||
#### isValidAddress(address) | ||
| Param | Type | Description | | ||
| --------- | ------ | ------------------------------------------------------------- | | ||
| hex | String | Hexadecimal string to check | | ||
| hexLength | Number | Hex length (should be equal `hex.length` without `0x` prefix) | | ||
| Param | Type | Description | | ||
| --------- | ------ | --------------------------------------------------- | | ||
| address | String | Address to check. Accepts checksummed addresses too | | ||
##### Returns | ||
`true` if hex is valid and `false` otherwise. | ||
`true` if address is valid and `false` otherwise. | ||
@@ -436,5 +435,22 @@ ##### Example | ||
```javascript | ||
const isValid = Keystore.isHexStringValid('0x8a02a99ee7a801da6996a2dacc406ffa5190dc9c', 40) | ||
const isValid = Keystore.isValidAddress('0x8a02a99ee7a801da6996a2dacc406ffa5190dc9c') | ||
``` | ||
#### isValidPrivateKey(privateKey) | ||
| Param | Type | Description | | ||
| ---------- | ------ | -------------------- | | ||
| privateKey | String | Private Key to check | | ||
##### Returns | ||
`true` if privateKey is valid and `false` otherwise. | ||
##### Example | ||
```javascript | ||
const pk = '0xa7fcb4efc392d2c8983cbfe64063f994f85120e60843407af95907d905d0dc9f' | ||
const isValid = Keystore.isValidPrivateKey(pk) | ||
``` | ||
#### isDerivationPathValid(derivationPath) | ||
@@ -441,0 +457,0 @@ |
@@ -13,4 +13,2 @@ const uuidv4 = require('uuid/v4') | ||
const ADDRESS_LENGTH = 40 | ||
const PRIVATE_KEY_LENGTH = 64 | ||
const ADDRESSES_PER_ITERATION_LIMIT = 5 | ||
@@ -47,6 +45,10 @@ | ||
static isHexStringValid(hash, hashLength) { | ||
return utils.isHexStringValid(hash, hashLength) | ||
static isValidAddress(address) { | ||
return utils.isValidAddress(address) | ||
} | ||
static isValidPrivateKey(privateKey) { | ||
return utils.isValidPrivateKey(privateKey) | ||
} | ||
static isDerivationPathValid(derivationPath) { | ||
@@ -310,6 +312,5 @@ return bitcore.HDPrivateKey.isValidPath(derivationPath) | ||
_createAddressAccount(props) { | ||
const { id, password, accountName } = props | ||
const privateKey = props.privateKey.toLowerCase() | ||
const { id, password, accountName, privateKey } = props | ||
if (!utils.isHexStringValid(privateKey, PRIVATE_KEY_LENGTH)) { | ||
if (!utils.isValidPrivateKey(privateKey)) { | ||
throw (new Error('Private Key is invalid')) | ||
@@ -319,5 +320,5 @@ } | ||
const address = utils.getAddressFromPrivateKey(privateKey) | ||
const addressLowerCase = address.toLowerCase() | ||
this._checkAccountUniqueness({ addressLowerCase }, 'address') | ||
this._checkAccountUniqueness({ address }, 'address') | ||
this.accounts.push({ | ||
@@ -327,2 +328,3 @@ type: this.addressType, | ||
address, | ||
addressLowerCase, | ||
accountName, | ||
@@ -337,10 +339,10 @@ isReadOnly: false, | ||
_createReadOnlyAddressAccount(props) { | ||
const { id, accountName } = props | ||
const address = props.address.toLowerCase() | ||
const { id, accountName, address } = props | ||
if (!utils.isHexStringValid(address, ADDRESS_LENGTH)) { | ||
if (!utils.isValidAddress(address)) { | ||
throw (new Error('Address is invalid')) | ||
} | ||
this._checkAccountUniqueness({ address }, 'address') | ||
const addressLowerCase = address.toLowerCase() | ||
this._checkAccountUniqueness({ addressLowerCase }, 'address') | ||
@@ -351,2 +353,3 @@ this.accounts.push({ | ||
address, | ||
addressLowerCase, | ||
accountName, | ||
@@ -353,0 +356,0 @@ isReadOnly: true, |
@@ -22,10 +22,6 @@ const Mnemonic = require('bitcore-mnemonic') | ||
function isBip32XPublicKeyValid(bip32XPublicKey) { | ||
if (!bip32XPublicKey) { | ||
if (!bip32XPublicKey || (bip32XPublicKey.length !== BIP32_EXTENDABLE_PUBLIC_KEY_LENGTH)) { | ||
return false | ||
} | ||
if (bip32XPublicKey.length !== BIP32_EXTENDABLE_PUBLIC_KEY_LENGTH) { | ||
return false | ||
} | ||
const re = new RegExp(`^(xpub)([A-Z\\d]{${BIP32_EXTENDABLE_PUBLIC_KEY_LENGTH - 4}})$`, 'i') | ||
@@ -32,0 +28,0 @@ |
@@ -7,15 +7,32 @@ const scrypt = require('scrypt.js') | ||
const ec = new EC('secp256k1') | ||
const HEX_PREFIX = /^0x/i | ||
function isHexStringValid(hex, length) { | ||
const requiredLengthWithPrefix = length + '0x'.length | ||
function isValidAddress(address) { | ||
return isNormalizedAddress(address) || isValidChecksumAddress(address) | ||
} | ||
if (hex.length !== requiredLengthWithPrefix) { | ||
return false | ||
} | ||
function isNormalizedAddress(address) { | ||
return (/^0x[0-9a-f]{40}$/.test(address) || /^0x[0-9A-F]{40}$/.test(address)) | ||
} | ||
const hexRe = new RegExp(`^(0x)([A-F\\d]{${length}})$`, 'i') | ||
function isValidChecksumAddress(address) { | ||
return (/^0x[0-9a-fA-F]{40}$/i.test(address) && getChecksum(address) === address) | ||
} | ||
return hexRe.test(hex) | ||
function getChecksum(address) { | ||
const addressLowerCase = strip0x(address).toLowerCase() | ||
const hash = cryptoJS.SHA3(addressLowerCase, { outputLength: 256 }).toString(cryptoJS.enc.Hex) | ||
const checksum = addressLowerCase | ||
.split('') | ||
.map((symbol, index) => ((parseInt(hash[index], 16) >= 8) ? symbol.toUpperCase() : symbol)) | ||
.join('') | ||
return add0x(checksum) | ||
} | ||
function isValidPrivateKey(privateKey) { | ||
return (/^0x[0-9a-fA-F]{64}$/i.test(privateKey)) | ||
} | ||
function getAddressFromPublicKey(publicKey) { | ||
@@ -28,6 +45,4 @@ const keyPair = ec.keyFromPublic(publicKey, 'hex') | ||
function getAddressFromPrivateKey(privateKey) { | ||
const privateKeyWithoutHexPrefix = privateKey.replace(/^0x/i, '') | ||
const keyPair = ec.genKeyPair() | ||
keyPair._importPrivate(privateKeyWithoutHexPrefix, 'hex') | ||
keyPair._importPrivate(strip0x(privateKey), 'hex') | ||
@@ -70,4 +85,8 @@ return getAddressFromKeyPair(keyPair) | ||
function strip0x(data) { | ||
return data.replace(HEX_PREFIX, '') | ||
} | ||
function add0x(data) { | ||
if (data.indexOf('0x') === 0) { | ||
if (HEX_PREFIX.test(data)) { | ||
return data | ||
@@ -80,3 +99,4 @@ } | ||
module.exports = { | ||
isHexStringValid, | ||
isValidAddress, | ||
isValidPrivateKey, | ||
getAddressFromPublicKey, | ||
@@ -83,0 +103,0 @@ getAddressFromPrivateKey, |
@@ -16,3 +16,3 @@ const should = require('should') | ||
privateKey: '0xa7fcb4efc392d2c8983cbfe64063f994f85120e60843407af95907d905d0dc9f', | ||
address: '0xb5c99109ded6212f667b9467a42dad1f195cdba9', | ||
address: '0xb5C99109DEd6212F667b9467a42DAD1F195cDBa9', | ||
} | ||
@@ -19,0 +19,0 @@ |
@@ -10,11 +10,14 @@ const should = require('should') | ||
const validPrivateKey = `0x${'1'.repeat(64)}` | ||
const invalidPrivateKey = `${validPrivateKey}%` | ||
const validPrivateKey = '0xa7fcb4efc392d2c8983cbfe64063f994f85120e60843407af95907d905d0dc9f' | ||
const invalidPrivateKey1 = validPrivateKey.slice(0, -1) | ||
const invalidPrivateKey2 = `${validPrivateKey}%` | ||
const validAddress = '0xb5C99109DEd6212F667b9467a42DAD1F195cDBa9' | ||
const invalidChecksumAddress = '0xb5C99109DEd6212F667b9467a42DAD1F195cdba9' | ||
const invalidAddress1 = validAddress.slice(0, -1) | ||
const invalidAddress2 = `${validAddress}a` | ||
const validBip32XPubKey = `xpub${'1'.repeat(107)}` | ||
const invalidBip32XPubKey = `${validBip32XPubKey}%` | ||
const validPrivateKeyLength = 64 | ||
const invalidPrivateKeyLength = 65 | ||
const validDerivationPath = "m/44'/60'/0'" | ||
@@ -84,6 +87,30 @@ const invalidDerivationPath = 'qwert' | ||
describe('isHexStringValid', function() { | ||
describe('isValidAddress', function() { | ||
it('should return true when address is correct', function(done) { | ||
const isAddressValid1 = Keystore.isValidAddress(validAddress) | ||
const isAddressValid2 = Keystore.isValidAddress(invalidChecksumAddress) | ||
const isAddressValid3 = Keystore.isValidAddress(invalidAddress1) | ||
const isAddressValid4 = Keystore.isValidAddress(invalidAddress2) | ||
isAddressValid1.should.be.a.Boolean() | ||
isAddressValid1.should.be.equal(true) | ||
isAddressValid2.should.be.a.Boolean() | ||
isAddressValid2.should.be.equal(false) | ||
isAddressValid3.should.be.a.Boolean() | ||
isAddressValid3.should.be.equal(false) | ||
isAddressValid4.should.be.a.Boolean() | ||
isAddressValid4.should.be.equal(false) | ||
done() | ||
}) | ||
}) | ||
describe('isValidPrivateKey', function() { | ||
it('should return true when private key is correct', function(done) { | ||
const isPrivateKeyValid1 = Keystore.isHexStringValid(validPrivateKey, validPrivateKeyLength) | ||
const isPrivateKeyValid2 = Keystore.isHexStringValid(invalidPrivateKey, invalidPrivateKeyLength) | ||
const isPrivateKeyValid1 = Keystore.isValidPrivateKey(validPrivateKey) | ||
const isPrivateKeyValid2 = Keystore.isValidPrivateKey(invalidPrivateKey1) | ||
const isPrivateKeyValid3 = Keystore.isValidPrivateKey(invalidPrivateKey2) | ||
@@ -96,2 +123,5 @@ isPrivateKeyValid1.should.be.a.Boolean() | ||
isPrivateKeyValid3.should.be.a.Boolean() | ||
isPrivateKeyValid3.should.be.equal(false) | ||
done() | ||
@@ -98,0 +128,0 @@ }) |
Sorry, the diff of this file is not supported yet
72372
2.9%1454
2.83%492
3.36%