-
Notifications
You must be signed in to change notification settings - Fork 0
/
account.js
182 lines (145 loc) · 5.95 KB
/
account.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
const crypto = require("crypto");
const argon2 = require("argon2");
const ed25519 = require("ed25519");
const bs58check = require("bs58check");
const assert = require("assert");
async function create_account(kdf_salt, iv, prv, password) {
let kdf_option = {
type: argon2.argon2d,
timeCost: 1,
memoryCost: 16 * 1024,
parallelism: 1,
hashLength: 32,
raw: true,
salt: kdf_salt,
version: 0x13
};
//password hashing
let derive_pwd = await argon2.hash(password, kdf_option);
//加密私钥,加密方法aes-256-ctr
let cipher = crypto.createCipheriv("aes-256-ctr", derive_pwd, iv);
let ciphertext = Buffer.concat([cipher.update(prv), cipher.final()]);
//生成公钥
let keypair = ed25519.MakeKeypair(prv);
let pub = keypair.publicKey;
console.log("kdf_salt: " + kdf_salt.toString('hex').toUpperCase());
console.log("password: " + password);
console.log("derive_pwd: " + derive_pwd.toString('hex').toUpperCase());
console.log("iv: " + iv.toString('hex').toUpperCase());
console.log("prv: " + prv.toString('hex').toUpperCase());
// account json file
// {
// "account":"czr_3M3dbuG3hWoeykQroyhJssdS15Bzocyh7wryG75qUWDxoyzBca",
// "kdf_salt":"AF8460A7D28A396C62D6C51620B87789C862ED8783374EEF7B783145F540EB19",
// "iv":"A695DDC35ED9F3183A09FED1E6D92083",
// "ciphertext":"1533D0D22D09C65110C6C5C1F6A3580C690FB0C444973FE31DC0916EAF2BCC8C"
// }
//clear prv for security, any better methed?
crypto.randomFillSync(derive_pwd);
crypto.randomFillSync(prv);
return {
pub: pub,
kdf_salt: kdf_salt,
iv: iv,
ciphertext: ciphertext
}
}
async function change_password(kdf_salt, iv, prv, password) {
let kdf_option = {
type: argon2.argon2d,
timeCost: 1,
memoryCost: 16 * 1024,
parallelism: 1,
hashLength: 32,
raw: true,
salt: kdf_salt,
version: 0x13
};
let derive_pwd = await argon2.hash(password, kdf_option);
let cipher = crypto.createCipheriv("aes-256-ctr", derive_pwd, iv);
let ciphertext = Buffer.concat([cipher.update(prv), cipher.final()]);
return ciphertext;
}
async function decrypt_account(kc, password) {
let kdf_option = {
type: argon2.argon2d,
timeCost: 1,
memoryCost: 16 * 1024,
parallelism: 1,
hashLength: 32,
raw: true,
salt: kc.kdf_salt,
version: 0x13
};
//password hashing
let derive_pwd = await argon2.hash(password, kdf_option);
//从ciphertext解密私钥
let decipher = crypto.createDecipheriv("aes-256-ctr", derive_pwd, kc.iv);
let prv = Buffer.concat([decipher.update(kc.ciphertext), decipher.final()]);
return prv;
}
function encode_account(pub) {
let version = Buffer.from([0x01]);
let v_pub = Buffer.concat([version, pub]);
let account = "czr_" + bs58check.encode(v_pub);
return account;
}
function decode_account(account) {
if (account.length < 54 || account[0] != 'c' || account[1] != 'z' || account[2] != 'r' || account[3] != '_')
return false;
let bs58str = account.slice(4);
let v_pub;
try { v_pub = bs58check.decode(bs58str); }
catch (e) { return false; }
if (v_pub.length != 33)
return false;
let version = v_pub.readUInt8(0);
if (version == 0x01) {
let pub = v_pub.slice(1);
return pub;
}
else
return false;
}
async function test_account() {
console.log("-------------------create_account-------------------------");
// let kdf_salt = crypto.randomBytes(32);
// let iv = crypto.randomBytes(16);
// let prv = crypto.randomBytes(32);
// let password = "123456";
let kdf_salt = Buffer.from("AF8460A7D28A396C62D6C51620B87789C862ED8783374EEF7B783145F540EB19", "hex");
let iv = Buffer.from("A695DDC35ED9F3183A09FED1E6D92083", "hex");
let prv = Buffer.from("5E844EE4D2E26920F8B0C4B7846929057CFCE48BF40BA269B173648999630053", "hex");
let password = "123456";
let kc = await create_account(kdf_salt, iv, prv, password);
console.log();
console.log("ciphertext: " + kc.ciphertext.toString('hex').toUpperCase());
console.log("pub: " + kc.pub.toString('hex').toUpperCase());
let account_c = encode_account(kc.pub);
console.log("account: " + account_c);
assert.ok(kc.ciphertext.toString('hex').toUpperCase() == "1533D0D22D09C65110C6C5C1F6A3580C690FB0C444973FE31DC0916EAF2BCC8C"
&& kc.pub.toString('hex').toUpperCase() == "34E85B176BE32EFAD87C9EB1EBFC6C54482A6BECBD297F9FDF3BFA8EA342162C"
&& account_c == "czr_3M3dbuG3hWoeykQroyhJssdS15Bzocyh7wryG75qUWDxoyzBca");
console.log("-------------------decrypt_account with right password-------------------------");
let prv1 = await decrypt_account(kc, password);
let keypair = ed25519.MakeKeypair(prv1);
let compare = keypair.publicKey;
console.log("compare: " + compare.toString('hex').toUpperCase());
assert.ok(kc.pub.equals(compare));
console.log("-------------------decrypt_account with wrong password-------------------------");
let wrong_password = "aaaa";
let prv2 = await decrypt_account(kc, wrong_password);
let keypair2 = ed25519.MakeKeypair(prv2);
let compare2 = keypair2.publicKey;
console.log("compare2: " + compare2.toString('hex').toUpperCase());
assert.ok(!kc.pub.equals(compare2));
console.log("-------------------account encoding-------------------------");
let pub = Buffer.from("5E844EE4D2E26920F8B0C4B7846929057CFCE48BF40BA269B173648999630053", "hex");
console.log("pub:" + pub.toString("hex").toUpperCase());
let account = encode_account(pub);
console.log("encode_account:" + account);//czr_3fNUxH2ix1TvrfEMK3s4SVq3YxEhYjzQxDjnYDtEYYKkYVumhu
let decode_pub = decode_account(account);
assert.ok(decode_pub && decode_pub.equals(pub));
console.log("decode_account:" + decode_pub.toString("hex").toUpperCase());
}
test_account();