-
Notifications
You must be signed in to change notification settings - Fork 0
/
stealthAddress.js
119 lines (105 loc) · 2.69 KB
/
stealthAddress.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
const stealth_version_byte = 0x32;
const crypto = require('crypto');
const bs58 = require('bs58');
module.exports = class StealthAddress {
constructor(scanPriv, scanPub, spendPriv, spendPub) {
this.scanPub = scanPub;
this.spendPub = spendPub;
this.scanPriv = scanPriv;
this.spendPriv = spendPriv;
this.options = 0;
}
encode() {
const address = new Buffer.from([
stealth_version_byte,
this.options,
...this.scanPub,
1, // size of public keys
...this.spendPub,
0, // size of signatures
0, // ??
]);
const result = Buffer.concat([address, this.generateChecksum(address)]);
return bs58.encode(result);
}
generateChecksum(data) {
return crypto
.createHash('sha256')
.update(
crypto
.createHash('sha256')
.update(data)
.digest()
)
.digest()
.slice(0, 4);
}
validateChecksum(modules) {
const buffered = new Buffer.from(modules);
const checksumModule = buffered.slice(
buffered.byteLength - 4,
buffered.byteLength
);
const informationModules = buffered.slice(0, buffered.byteLength - 4);
const informationChecksum = this.generateChecksum(informationModules);
return {
valid: Buffer.compare(informationChecksum, checksumModule) === 0,
checksum: informationChecksum.toString('hex'),
};
}
isStealth(bs58address) {
const modules = bs58.decode(bs58address);
let checks = this.validateChecksum(modules);
if (!checks.valid) {
return {
valid: false,
};
}
if (modules.length < 1 + 1 + 33 + 1 + 33 + 1 + 1 + 4) {
return {
valid: false,
};
}
checks = { ...checks, length: modules.length };
if (modules[0] !== stealth_version_byte) {
return {
valid: false,
};
}
checks = {
...checks,
stealthVersion: `0x${modules[0].toString('16')}`,
};
return checks;
}
toJsonPrivate() {
return JSON.stringify(
{
scanPub: this.scanPub.toString('hex'),
spendPub: this.spendPub.toString('hex'),
scanPriv: this.scanPriv.toString('hex'),
spendPriv: this.spendPriv.toString('hex'),
options: this.options,
address: this.encode(),
isStealth: this.isStealth(this.encode()),
},
null,
2
);
}
toJson() {
return JSON.stringify(
{
scanPub: this.scanPub.toString('hex'),
spendPub: this.spendPub.toString('hex'),
scanPriv: 'hidden',
spendPriv: 'hidden',
options: this.options,
address: this.encode(),
isStealth: this.isStealth(this.encode()),
},
null,
2
);
}
};