UNPKG

4.03 kBJavaScriptView Raw
1let {isString, isArray} = require('underscore')
2let patterns = require('./patterns')
3let values = require('./values')
4let {blake2b256, nacl} = require('./crypto')
5
6let {
7 prependZeroX,
8 removeLeadingZeroX,
9 randomHexBuffer,
10 bufferToZeroXHex,
11 toBuffer
12} = require('./formats')
13
14let validNonA0PrefixAddresses = [
15 "0000000000000000000000000000000000000000000000000000000000000200",
16 "08efa07244bacb5dc92daef46474560b57e9cfc2be62072fa21decf64051a317",
17 "0a0b61014dc764640ee6087095faf68dfeb4e4b9ee681225611fea65932c93e4",
18 "1318abaea6686c79eaa4ba37f5eef843bd065e74560ed1094133641b4f2395b8",
19 "24a970ec53022623d95989e3340ff180a843c8645841699c4c19a227287901cf",
20 "38dd1ae75523611bed9d4b647016dc8b0735c42317bd03e9bd65ceca69e8c46c",
21 "64b09d162e2f91d3308381f28c02b9d0e5cb4270a43465b696e1db6210aad189",
22 "7b8289c4b1ada70af8794b508f6db000ca25f1d1821c053da302a0403f73b29e",
23 "aebf26d4d5438304e277a3d5104a3b056d8617f586f33560d4b2e7984a2bfe01",
24 "af504da64d6cb7ec06a462b2c43a3cb4e482db3b41fde42b537f4c64fedc894b",
25 "af694e98b964b275d723c2c66e224739d97d36125bba985215bca1075656b82e",
26 "c00dcc9fe51c73767fad07cd4da990a8aa7487f40ba5718f711b4fdc09ae5b6e",
27 "cb68ed818e6f712b315d53e0cce541b2d2e4c0d101ef1fcc91bccef1c21dffd7",
28 "d801109bab93a4ab71c16e85389d9c366a23a975693cbdcc7e6db85561f1d5ce",
29 "f5079727f0c503b5eae232dbd303128338576fc1db867892ae07dcc920691ab9"
30];
31
32// address + message signature length
33let aionPubSigLen = nacl.sign.publicKeyLength + nacl.sign.signatureLength
34
35function createKeyPair({entropy, privateKey}) {
36 let kp
37 let keyPair
38 let ent
39 let priv
40
41 if (privateKey !== undefined) {
42 priv = toBuffer(privateKey)
43 kp = nacl.sign.keyPair.fromSecretKey(priv)
44 keyPair = {
45 _privateKey: priv,
46 privateKey: bufferToZeroXHex(priv),
47 publicKey: toBuffer(kp.publicKey)
48 }
49 return keyPair
50 }
51
52 if (entropy === undefined) {
53 ent = randomHexBuffer()
54 }
55
56 if (typeof entropy === 'string') {
57 ent = toBuffer(entropy)
58 }
59
60 // entropy sandwich
61 ent = Buffer.concat([
62 blake2b256(randomHexBuffer()), // bread
63 blake2b256(ent), // peanut butter
64 blake2b256(randomHexBuffer()) // bread 😉
65 ])
66
67 kp = nacl.sign.keyPair.fromSeed(ent.slice(0, nacl.sign.seedLength))
68 priv = toBuffer(kp.secretKey)
69 keyPair = {
70 _privateKey: priv,
71 privateKey: bufferToZeroXHex(priv),
72 publicKey: toBuffer(kp.publicKey)
73 }
74 return keyPair
75}
76
77let isPrivateKey = val =>
78 (isArray(val) === true || Buffer.isBuffer(val) === true) && val.length > 0
79
80function createA0Address(publicKey) {
81 let pkHash = Buffer.from(blake2b256(publicKey)).slice(1, 32)
82 let address = Buffer.concat([values.addresses.identifier, pkHash], 32)
83 return prependZeroX(address.toString('hex'))
84}
85
86function isAccountAddress(val) {
87 if (val === undefined || isString(val) === false) {
88 return false
89 }
90
91 return patterns.address.test(val) === true ||
92 (patterns.hash.test(val) && validNonA0PrefixAddresses.indexOf(val.replace(/^0x/, "")) > 0)
93}
94
95function bit(arr, index) {
96 let byteOffset = Math.floor(index / 8)
97 let bitOffset = index % 8
98 let uint8 = arr[byteOffset]
99 return (uint8 >> bitOffset) & 0x1
100}
101
102function createChecksumAddress(val) {
103 let address = removeLeadingZeroX(val.toLowerCase())
104 let addressHash = blake2b256(toBuffer(address))
105
106 return prependZeroX(
107 address
108 .split('')
109 .map((item, index) => {
110 let char = address[index]
111
112 if (isNaN(char) === false) {
113 // numeric
114 return char
115 }
116
117 return bit(addressHash, index) === 1
118 ? char.toUpperCase()
119 : char.toLowerCase()
120 })
121 .join('')
122 )
123}
124
125let isValidChecksumAddress = val => val === createChecksumAddress(val)
126
127function equalAddresses(addr1, addr2) {
128 return (
129 removeLeadingZeroX(addr1.toLowerCase()) ===
130 removeLeadingZeroX(addr2.toLowerCase())
131 )
132}
133
134module.exports = {
135 createKeyPair,
136 isPrivateKey,
137 createA0Address,
138 isAccountAddress,
139 createChecksumAddress,
140 isValidChecksumAddress,
141 equalAddresses,
142 aionPubSigLen
143}