KeystoreWallet Class & Decrypt (#111)
* add keystore decrypt functionality * add flow types * add KeystoreWallet class * only support keystore as string
This commit is contained in:
parent
187d2e16ad
commit
30f2d854d6
|
@ -1,5 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { randomBytes, createCipheriv } from 'crypto';
|
import {
|
||||||
|
randomBytes,
|
||||||
|
createCipheriv,
|
||||||
|
pbkdf2Sync,
|
||||||
|
createDecipheriv
|
||||||
|
} from 'crypto';
|
||||||
import { sha3 } from 'ethereumjs-util';
|
import { sha3 } from 'ethereumjs-util';
|
||||||
import scrypt from 'scryptsy';
|
import scrypt from 'scryptsy';
|
||||||
import uuid from 'uuid';
|
import uuid from 'uuid';
|
||||||
|
@ -69,3 +74,57 @@ export function getV3Filename(address: string) {
|
||||||
const ts = new Date();
|
const ts = new Date();
|
||||||
return ['UTC--', ts.toJSON().replace(/:/g, '-'), '--', address].join('');
|
return ['UTC--', ts.toJSON().replace(/:/g, '-'), '--', address].join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fromV3KeystoreToPkey(input: string, password: string): Buffer {
|
||||||
|
let kstore = JSON.parse(input.toLowerCase());
|
||||||
|
if (kstore.version !== 3) {
|
||||||
|
throw new Error('Not a V3 wallet');
|
||||||
|
}
|
||||||
|
let derivedKey, kdfparams;
|
||||||
|
|
||||||
|
if (kstore.crypto.kdf === 'scrypt') {
|
||||||
|
kdfparams = kstore.crypto.kdfparams;
|
||||||
|
derivedKey = scrypt(
|
||||||
|
new Buffer(password),
|
||||||
|
new Buffer(kdfparams.salt, 'hex'),
|
||||||
|
kdfparams.n,
|
||||||
|
kdfparams.r,
|
||||||
|
kdfparams.p,
|
||||||
|
kdfparams.dklen
|
||||||
|
);
|
||||||
|
} else if (kstore.crypto.kdf === 'pbkdf2') {
|
||||||
|
kdfparams = kstore.crypto.kdfparams;
|
||||||
|
if (kdfparams.prf !== 'hmac-sha256') {
|
||||||
|
throw new Error('Unsupported parameters to PBKDF2');
|
||||||
|
}
|
||||||
|
derivedKey = pbkdf2Sync(
|
||||||
|
new Buffer(password),
|
||||||
|
new Buffer(kdfparams.salt, 'hex'),
|
||||||
|
kdfparams.c,
|
||||||
|
kdfparams.dklen,
|
||||||
|
'sha256'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Error('Unsupported key derivation scheme');
|
||||||
|
}
|
||||||
|
let ciphertext = new Buffer(kstore.crypto.ciphertext, 'hex');
|
||||||
|
let mac = sha3(Buffer.concat([derivedKey.slice(16, 32), ciphertext]));
|
||||||
|
if (mac.toString('hex') !== kstore.crypto.mac) {
|
||||||
|
throw new Error('Key derivation failed - possibly wrong passphrase');
|
||||||
|
}
|
||||||
|
let decipher = createDecipheriv(
|
||||||
|
kstore.crypto.cipher,
|
||||||
|
derivedKey.slice(0, 16),
|
||||||
|
new Buffer(kstore.crypto.cipherparams.iv, 'hex')
|
||||||
|
);
|
||||||
|
let seed = decipherBuffer(decipher, ciphertext, 'hex');
|
||||||
|
while (seed.length < 32) {
|
||||||
|
let nullBuff = new Buffer([0x00]);
|
||||||
|
seed = Buffer.concat([nullBuff, seed]);
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decipherBuffer(decipher, data) {
|
||||||
|
return Buffer.concat([decipher.update(data), decipher.final()]);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// @flow
|
||||||
|
import PrivKeyWallet from './privkey';
|
||||||
|
import { fromV3KeystoreToPkey } from 'libs/keystore';
|
||||||
|
|
||||||
|
export default class KeystoreWallet extends PrivKeyWallet {
|
||||||
|
constructor(keystore: string, password: string) {
|
||||||
|
super(fromV3KeystoreToPkey(keystore, password));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue