Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ultraviolet
GitHub Repository: ultraviolet/bitaddress.org
Path: blob/master/src/bitcoinjs-lib.eckey.js
248 views
1
Bitcoin.KeyPool = (function () {
2
var KeyPool = function () {
3
this.keyArray = [];
4
5
this.push = function (item) {
6
if (item == null || item.priv == null) return;
7
var doAdd = true;
8
// prevent duplicates from being added to the array
9
for (var index in this.keyArray) {
10
var currentItem = this.keyArray[index];
11
if (currentItem != null && currentItem.priv != null && item.getBitcoinAddress() == currentItem.getBitcoinAddress()) {
12
doAdd = false;
13
break;
14
}
15
}
16
if (doAdd) this.keyArray.push(item);
17
};
18
19
this.reset = function () {
20
this.keyArray = [];
21
};
22
23
this.getArray = function () {
24
// copy array
25
return this.keyArray.slice(0);
26
};
27
28
this.setArray = function (ka) {
29
this.keyArray = ka;
30
};
31
32
this.length = function () {
33
return this.keyArray.length;
34
};
35
36
this.toString = function () {
37
var keyPoolString = "# = " + this.length() + "\n";
38
var pool = this.getArray();
39
for (var index in pool) {
40
var item = pool[index];
41
if (Bitcoin.Util.hasMethods(item, 'getBitcoinAddress', 'toString')) {
42
if (item != null) {
43
keyPoolString += "\"" + item.getBitcoinAddress() + "\"" + ", \"" + item.toString("wif") + "\"\n";
44
}
45
}
46
}
47
48
return keyPoolString;
49
};
50
51
return this;
52
};
53
54
return new KeyPool();
55
})();
56
57
Bitcoin.Bip38Key = (function () {
58
var Bip38 = function (address, encryptedKey) {
59
this.address = address;
60
this.priv = encryptedKey;
61
};
62
63
Bip38.prototype.getBitcoinAddress = function () {
64
return this.address;
65
};
66
67
Bip38.prototype.toString = function () {
68
return this.priv;
69
};
70
71
return Bip38;
72
})();
73
74
//https://raw.github.com/pointbiz/bitcoinjs-lib/9b2f94a028a7bc9bed94e0722563e9ff1d8e8db8/src/eckey.js
75
Bitcoin.ECKey = (function () {
76
var ECDSA = Bitcoin.ECDSA;
77
var KeyPool = Bitcoin.KeyPool;
78
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
79
80
var ECKey = function (input) {
81
if (!input) {
82
// Generate new key
83
var n = ecparams.getN();
84
this.priv = ECDSA.getBigRandom(n);
85
} else if (input instanceof BigInteger) {
86
// Input is a private key value
87
this.priv = input;
88
} else if (Bitcoin.Util.isArray(input)) {
89
// Prepend zero byte to prevent interpretation as negative integer
90
this.priv = BigInteger.fromByteArrayUnsigned(input);
91
} else if ("string" == typeof input) {
92
var bytes = null;
93
try{
94
if (ECKey.isWalletImportFormat(input)) {
95
bytes = ECKey.decodeWalletImportFormat(input);
96
} else if (ECKey.isCompressedWalletImportFormat(input)) {
97
bytes = ECKey.decodeCompressedWalletImportFormat(input);
98
this.compressed = true;
99
} else if (ECKey.isMiniFormat(input)) {
100
bytes = Crypto.SHA256(input, { asBytes: true });
101
} else if (ECKey.isHexFormat(input)) {
102
bytes = Crypto.util.hexToBytes(input);
103
} else if (ECKey.isBase64Format(input)) {
104
bytes = Crypto.util.base64ToBytes(input);
105
}
106
} catch (exc1) {
107
this.setError(exc1);
108
}
109
110
if (ECKey.isBase6Format(input)) {
111
this.priv = new BigInteger(input, 6);
112
} else if (bytes == null || bytes.length != 32) {
113
this.priv = null;
114
} else {
115
// Prepend zero byte to prevent interpretation as negative integer
116
this.priv = BigInteger.fromByteArrayUnsigned(bytes);
117
}
118
}
119
120
this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed;
121
try {
122
// check not zero
123
if (this.priv != null && BigInteger.ZERO.compareTo(this.priv) == 0) this.setError("Error: BigInteger equal to zero.");
124
// valid range [0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140])
125
var hexKeyRangeLimit = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140";
126
var rangeLimitBytes = Crypto.util.hexToBytes(hexKeyRangeLimit);
127
var limitBigInt = BigInteger.fromByteArrayUnsigned(rangeLimitBytes);
128
if (this.priv != null && limitBigInt.compareTo(this.priv) < 0) this.setError("Error: BigInteger outside of curve range.")
129
130
if (this.priv != null) {
131
KeyPool.push(this);
132
}
133
} catch (exc2) {
134
this.setError(exc2);
135
}
136
};
137
138
ECKey.privateKeyPrefix = 0x80; // mainnet 0x80 testnet 0xEF
139
140
/**
141
* Whether public keys should be returned compressed by default.
142
*/
143
ECKey.compressByDefault = false;
144
145
/**
146
* Set whether the public key should be returned compressed or not.
147
*/
148
ECKey.prototype.setError = function (err) {
149
this.error = err;
150
this.priv = null;
151
return this;
152
};
153
154
/**
155
* Set whether the public key should be returned compressed or not.
156
*/
157
ECKey.prototype.setCompressed = function (v) {
158
this.compressed = !!v;
159
if (this.pubPoint) this.pubPoint.compressed = this.compressed;
160
return this;
161
};
162
163
/*
164
* Return public key as a byte array in DER encoding
165
*/
166
ECKey.prototype.getPub = function () {
167
if (this.compressed) {
168
if (this.pubComp) return this.pubComp;
169
return this.pubComp = this.getPubPoint().getEncoded(1);
170
} else {
171
if (this.pubUncomp) return this.pubUncomp;
172
return this.pubUncomp = this.getPubPoint().getEncoded(0);
173
}
174
};
175
176
/**
177
* Return public point as ECPoint object.
178
*/
179
ECKey.prototype.getPubPoint = function () {
180
if (!this.pubPoint) {
181
this.pubPoint = ecparams.getG().multiply(this.priv);
182
this.pubPoint.compressed = this.compressed;
183
}
184
return this.pubPoint;
185
};
186
187
ECKey.prototype.getPubKeyHex = function () {
188
if (this.compressed) {
189
if (this.pubKeyHexComp) return this.pubKeyHexComp;
190
return this.pubKeyHexComp = Crypto.util.bytesToHex(this.getPub()).toString().toUpperCase();
191
} else {
192
if (this.pubKeyHexUncomp) return this.pubKeyHexUncomp;
193
return this.pubKeyHexUncomp = Crypto.util.bytesToHex(this.getPub()).toString().toUpperCase();
194
}
195
};
196
197
/**
198
* Get the pubKeyHash for this key.
199
*
200
* This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as
201
* a byte array.
202
*/
203
ECKey.prototype.getPubKeyHash = function () {
204
if (this.compressed) {
205
if (this.pubKeyHashComp) return this.pubKeyHashComp;
206
return this.pubKeyHashComp = Bitcoin.Util.sha256ripe160(this.getPub());
207
} else {
208
if (this.pubKeyHashUncomp) return this.pubKeyHashUncomp;
209
return this.pubKeyHashUncomp = Bitcoin.Util.sha256ripe160(this.getPub());
210
}
211
};
212
213
ECKey.prototype.getBitcoinAddress = function () {
214
var hash = this.getPubKeyHash();
215
var addr = new Bitcoin.Address(hash);
216
return addr.toString();
217
};
218
219
/*
220
* Takes a public point as a hex string or byte array
221
*/
222
ECKey.prototype.setPub = function (pub) {
223
// byte array
224
if (Bitcoin.Util.isArray(pub)) {
225
pub = Crypto.util.bytesToHex(pub).toString().toUpperCase();
226
}
227
var ecPoint = ecparams.getCurve().decodePointHex(pub);
228
this.setCompressed(ecPoint.compressed);
229
this.pubPoint = ecPoint;
230
return this;
231
};
232
233
// Sipa Private Key Wallet Import Format
234
ECKey.prototype.getBitcoinWalletImportFormat = function () {
235
var bytes = this.getBitcoinPrivateKeyByteArray();
236
if (bytes == null) return "";
237
bytes.unshift(ECKey.privateKeyPrefix); // prepend 0x80 byte
238
if (this.compressed) bytes.push(0x01); // append 0x01 byte for compressed format
239
var checksum = Crypto.SHA256(Crypto.SHA256(bytes, { asBytes: true }), { asBytes: true });
240
bytes = bytes.concat(checksum.slice(0, 4));
241
var privWif = Bitcoin.Base58.encode(bytes);
242
return privWif;
243
};
244
245
// Private Key Hex Format
246
ECKey.prototype.getBitcoinHexFormat = function () {
247
return Crypto.util.bytesToHex(this.getBitcoinPrivateKeyByteArray()).toString().toUpperCase();
248
};
249
250
// Private Key Base64 Format
251
ECKey.prototype.getBitcoinBase64Format = function () {
252
return Crypto.util.bytesToBase64(this.getBitcoinPrivateKeyByteArray());
253
};
254
255
ECKey.prototype.getBitcoinPrivateKeyByteArray = function () {
256
if (this.priv == null) return null;
257
// Get a copy of private key as a byte array
258
var bytes = this.priv.toByteArrayUnsigned();
259
// zero pad if private key is less than 32 bytes
260
while (bytes.length < 32) bytes.unshift(0x00);
261
return bytes;
262
};
263
264
ECKey.prototype.toString = function (format) {
265
format = format || "";
266
if (format.toString().toLowerCase() == "base64" || format.toString().toLowerCase() == "b64") {
267
return this.getBitcoinBase64Format();
268
}
269
// Wallet Import Format
270
else if (format.toString().toLowerCase() == "wif") {
271
return this.getBitcoinWalletImportFormat();
272
}
273
else {
274
return this.getBitcoinHexFormat();
275
}
276
};
277
278
ECKey.prototype.sign = function (hash) {
279
return ECDSA.sign(hash, this.priv);
280
};
281
282
ECKey.prototype.verify = function (hash, sig) {
283
return ECDSA.verify(hash, sig, this.getPub());
284
};
285
286
/**
287
* Parse a wallet import format private key contained in a string.
288
*/
289
ECKey.decodeWalletImportFormat = function (privStr) {
290
var bytes = Bitcoin.Base58.decode(privStr);
291
var hash = bytes.slice(0, 33);
292
var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true });
293
if (checksum[0] != bytes[33] ||
294
checksum[1] != bytes[34] ||
295
checksum[2] != bytes[35] ||
296
checksum[3] != bytes[36]) {
297
throw "Checksum validation failed!";
298
}
299
var version = hash.shift();
300
if (version != ECKey.privateKeyPrefix) {
301
throw "Version " + version + " not supported!";
302
}
303
return hash;
304
};
305
306
/**
307
* Parse a compressed wallet import format private key contained in a string.
308
*/
309
ECKey.decodeCompressedWalletImportFormat = function (privStr) {
310
var bytes = Bitcoin.Base58.decode(privStr);
311
var hash = bytes.slice(0, 34);
312
var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true });
313
if (checksum[0] != bytes[34] ||
314
checksum[1] != bytes[35] ||
315
checksum[2] != bytes[36] ||
316
checksum[3] != bytes[37]) {
317
throw "Checksum validation failed!";
318
}
319
var version = hash.shift();
320
if (version != ECKey.privateKeyPrefix) {
321
throw "Version " + version + " not supported!";
322
}
323
hash.pop();
324
return hash;
325
};
326
327
// 64 characters [0-9A-F]
328
ECKey.isHexFormat = function (key) {
329
key = key.toString();
330
return /^[A-Fa-f0-9]{64}$/.test(key);
331
};
332
333
// 51 characters base58, always starts with a '5'
334
ECKey.isWalletImportFormat = function (key) {
335
key = key.toString();
336
return (ECKey.privateKeyPrefix == 0x80) ?
337
(/^5[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{50}$/.test(key)) :
338
(/^9[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{50}$/.test(key));
339
};
340
341
// 52 characters base58
342
ECKey.isCompressedWalletImportFormat = function (key) {
343
key = key.toString();
344
return (ECKey.privateKeyPrefix == 0x80) ?
345
(/^[LK][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{51}$/.test(key)) :
346
(/^c[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{51}$/.test(key));
347
};
348
349
// 44 characters
350
ECKey.isBase64Format = function (key) {
351
key = key.toString();
352
return (/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=+\/]{44}$/.test(key));
353
};
354
355
// 99 characters, 1=1, if using dice convert 6 to 0
356
ECKey.isBase6Format = function (key) {
357
key = key.toString();
358
return (/^[012345]{99}$/.test(key));
359
};
360
361
// 22, 26 or 30 characters, always starts with an 'S'
362
ECKey.isMiniFormat = function (key) {
363
key = key.toString();
364
var validChars22 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21}$/.test(key);
365
var validChars26 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{25}$/.test(key);
366
var validChars30 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{29}$/.test(key);
367
var testBytes = Crypto.SHA256(key + "?", { asBytes: true });
368
369
return ((testBytes[0] === 0x00 || testBytes[0] === 0x01) && (validChars22 || validChars26 || validChars30));
370
};
371
372
return ECKey;
373
})();
374