-
Notifications
You must be signed in to change notification settings - Fork 12
/
main.js
executable file
·304 lines (281 loc) · 8.41 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
var EC = require("elliptic").ec;
var EdDSA = require("elliptic").eddsa;
var pbkdf2 = require("pbkdf2");
var scrypt = require("scrypt-js");
var bs58 = require("bs58");
var shajs = require("sha.js");
var Ripemd160 = require("ripemd160");
var keccak = require("keccak");
var BN = require("bn.js");
var argon2 = require("argon2-browser");
var Worker = require("./argon.worker.js");
var s256 = new EC("secp256k1");
var ed25519 = new EdDSA("ed25519");
function sha256(s) {
return shajs("sha256")
.update(s)
.digest();
}
function ripemd160(s) {
return new Ripemd160().update(s).digest();
}
function keccak256(s) {
return keccak("keccak256")
.update(s)
.digest();
}
function keccak256(s) {
return keccak("keccak256")
.update(s)
.digest();
}
function reduce32(s) {
return new BN(s, "le")
.mod(
new BN(
"1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
16
)
)
.toArrayLike(Buffer, "le", 32);
}
function b58checkencode(version, unbufferedKey) {
var buffer = Buffer.from(unbufferedKey);
buffer = Buffer.concat([Buffer.alloc(1, version), buffer]);
var hash = sha256(sha256(buffer));
buffer = Buffer.concat([buffer, hash.slice(0, 4)]);
var encoded = bs58.encode(buffer);
return encoded;
}
function keyToBitcoinish(key, version) {
var pubkey = new Buffer(
s256.keyFromPrivate(key).getPublic(false, "hex"),
"hex"
);
return {
private: b58checkencode(version + 0x80, key),
public: b58checkencode(version, ripemd160(sha256(pubkey)))
};
}
function keyToBitcoin(key) {
return keyToBitcoinish(key, 0);
}
function keyToLitecoin(key) {
return keyToBitcoinish(key, 48);
}
function keyToEthereum(key) {
var pubkey = new Buffer(
s256.keyFromPrivate(key).getPublic(false, "hex"),
"hex"
);
return {
private: key.toString("hex"),
public:
"0x" +
keccak256(pubkey.slice(1))
.slice(12)
.toString("hex")
};
}
function keyToMonero(seed) {
var private_spend = reduce32(seed);
var private_view = reduce32(keccak256(private_spend));
// Hack
var kp = ed25519.keyFromSecret();
kp._privBytes = Array.from(private_spend);
var public_spend = new Buffer(kp.pubBytes());
var kp = ed25519.keyFromSecret();
kp._privBytes = Array.from(private_view);
var public_view = new Buffer(kp.pubBytes());
var address_buf = Buffer.concat([
Buffer.alloc(1, 0x12),
public_spend,
public_view
]);
address_buf = Buffer.concat([
address_buf,
keccak256(address_buf).slice(0, 4)
]);
var address = "";
for (var i = 0; i < 8; i++) {
address += bs58.encode(address_buf.slice(i * 8, i * 8 + 8));
}
address += bs58.encode(address_buf.slice(64, 69));
return {
private_spend: private_spend.toString("hex"),
private_view: private_view.toString("hex"),
public_spend: public_spend.toString("hex"),
public_view: public_view.toString("hex"),
public: address
};
}
/*
argon2.hash({
// required
pass: 'password',
salt: 'salt',
// optional
time: 1, // the number of iterations
mem: 1024, // used memory, in KiB
hashLen: 24, // desired hash length
parallelism: 1, // desired parallelism (will be computed in parallel only for PNaCl)
type: argon2.ArgonType.Argon2d, // or argon2.ArgonType.Argon2i
distPath: '' // asm.js script location, without trailing slash
})
// result
.then(res => {
console.log(res.hash) // hash as Uint8Array
console.log(res.hashHex) // hash as hex-string
console.log(res.encoded) // encoded hash, as required by argon2
})
// or error
.catch(err => {
console.log(err.message) // error message as string, if available
console.log(err.code) // numeric error code
})
*/
function allocateArray(strOrArr) {
var arr =
strOrArr instanceof Uint8Array || strOrArr instanceof Array
? strOrArr
: intArrayFromString(strOrArr);
return allocate(arr, "i8", ALLOC_NORMAL);
}
/* salt The salt to use, at least 8 characters
-i Use Argon2i (this is the default)
-d Use Argon2d instead of Argon2i
-id Use Argon2id instead of Argon2i
-t N Sets the number of iterations to N (default = 3)
-m N Sets the memory usage of 2^N KiB (default 12)
-k N Sets the memory usage of N KiB (default 4096)
-p N Sets parallelism to N threads (default 1)
-l N Sets hash output length to N bytes (default 32)
-e Output only encoded hash
-r Output only the raw bytes of the hash
-v (10|13) Argon2 version (defaults to the most recent version, currently 13)
-h Print ./argon2 usage
v*/
function now() {
return performance ? performance.now() : Date.now();
}
function warpwallet(password, salt, power, hashSuffix, callback) {
/*var arg = {};
var t_cost = arg && arg.time || 10;
var m_cost = arg && arg.mem || 4096;
var parallelism = arg && arg.parallelism || 1;
var pwd = allocateArray(arg && arg.pass || 'password');
var pwdlen = arg && arg.pass ? arg.pass.length : 8;
var salt = allocateArray(arg && arg.salt || 'somesalt');
var saltlen = arg && arg.salt ? arg.salt.length : 8;
var hash = allocate(new Array(arg && arg.hashLen || 32), 'i8', ALLOC_NORMAL);
var hashlen = arg && arg.hashLen || 32;
var encoded = allocate(new Array(512), 'i8', ALLOC_NORMAL);
var encodedlen = 512;
var argon2_type = arg && arg.type || 0;
var version = 0x13;
*/
var password_buffer = Buffer.from(password, "utf-8");
var salt_buffer = Buffer.from(salt, "utf-8");
var x1 = Buffer.alloc(1, hashSuffix);
var x2 = Buffer.alloc(1, hashSuffix + 1);
var workerData = {
pass: password,
salt: salt,
hashSuffix: hashSuffix
};
const worker = new Worker();
worker.postMessage(workerData);
worker.onmessage = function(event) {
console.log(event.data);
if (event.data.hashSuffix != 4) {
callback(event.data.status, event.data.bufferkey);
} else {
callback(event.data.status, event.data.strkey);
}
};
//,,,
console.log("no worker", argon2.ArgonType.Argon2i);
callback(0.1, null);
//cheating a bit here to show some progress and not make the user leave in dispair
setTimeout(function() {
callback(0.2, null);
}, 5000);
setTimeout(function() {
callback(0.4, null);
}, 15000);
setTimeout(function() {
callback(0.6, null);
}, 30000);
setTimeout(function() {
callback(0.7, null);
}, 35000);
/* argon2.hash({
// required
pass: password,
salt: salt,
// optional
time: 262144, // the number of iterations
mem: 8, // used memory, in KiB
hashLen: 32, // desired hash length
parallelism: 1, // desired parallelism (will be computed in parallel only for PNaCl)
type: argon2.ArgonType.Argon2i, // or argon2.ArgonType.Argon2i
distPath: '' // asm.js script location, without trailing slash
})
// result
.then(res => {
callback(0.3, null);
console.log(res.hash) // hash as Uint8Array
console.log(res.hashHex) // hash as hex-string
console.log(res.encoded) // encoded hash, as required by argon2
var key1 = res.hash;
pbkdf2.pbkdf2(Buffer.concat([password_buffer, x2]), Buffer.concat([salt_buffer, x2]), Math.pow(2, 16), 32, 'sha256', function(err, key2) {
for (var i = 0; i < 32; i++) {
key2[i] = key2[i] ^ key1[i];
}
//console.log(key2.toString('hex'));
callback(1, key2);
});
})
// or error
.catch(err => {
console.log(err.message) // error message as string, if available
console.log(err.code) // numeric error code
})*/
//callback(progress, null);
}
var currencies = {
bitcoin: {
fn: keyToBitcoin,
hashSuffix: 1
},
litecoin: {
fn: keyToLitecoin,
hashSuffix: 2
},
monero: {
fn: keyToMonero,
hashSuffix: 3
},
ethereum: {
fn: keyToEthereum,
hashSuffix: 4
}
};
function generateWallet(passphrase, salt, currency, callback) {
warpwallet(passphrase, salt, 18, currencies[currency].hashSuffix, function(
progress,
result
) {
if (result) {
var wallet = currencies[currency].fn(result);
callback(1, wallet);
} else {
callback(progress, null);
}
});
}
module.exports = {
generateWallet: generateWallet
};
//warpwallet('hello', '[email protected]', 10);
//warpwallet('hello', '[email protected]', 18);