KeyStore.fromV1Json constructor
Reads and unlocks the key store denoted in the json string given with the
specified password
. encoded
must be the String contents of a valid
v1 Topl key store.
Implementation
factory KeyStore.fromV1Json(String encoded, String password) {
/*
In order to read the keystore and obtain the secret key stored in it, we
need to do the following:
1: Key Derivation: Based on the key derivator specified (either pbdkdf2 or
scryt), we need to use the password to obtain the aes key used to
decrypt the private key.
2: Using the obtained aes key and the iv parameter, decrypt the private
key stored in the keystore.
*/
final data = json.decode(encoded);
// Ensure version is 1, only version that we support at the moment
final version = data['version'];
if (version != 1) {
throw ArgumentError.value(
version,
'version',
'Library only supports '
'version 1 of key store files at the moment. However, the following value'
' has been given:');
}
final crypto = data['crypto'] ?? data['Crypto'];
_KeyDerivator derivator;
final kdf = crypto['kdf'] as String;
switch (kdf) {
case 'scrypt':
final derParams = crypto['kdfparams'] as Map<String, dynamic>;
derivator = _ScryptKeyDerivator(
derParams['dkLen'] as int,
derParams['n'] as int,
derParams['r'] as int,
derParams['p'] as int,
Uint8List.fromList(str2ByteArray(derParams['salt'] as String)));
break;
default:
throw ArgumentError(
'Wallet file uses $kdf as key derivation function which is currently not supported');
}
// Now that we have the derivator, let's obtain the aes key:
final encodedPassword =
Uint8List.fromList(str2ByteArray(password, enc: 'latin1'));
final derivedKey = derivator.deriveKey(encodedPassword);
final encryptedPrivateKey = str2ByteArray(crypto['cipherText'] as String);
//Validate the derived key with the mac provided
final derivedMac = _getMac(derivedKey, encryptedPrivateKey);
if (derivedMac != crypto['mac']) {
throw ArgumentError(
'Invalid MAC: Could not unlock key store file. You either supplied the wrong password or the file is corrupted');
}
// We only support this mode at the moment
if (crypto['cipher'] != 'aes-256-ctr') {
throw ArgumentError(
'Invalid Cipher: key store file uses ${crypto["cipher"]} as cipher, but only aes-256-ctr is supported.');
}
final iv = str2ByteArray(crypto['cipherParams']['iv'] as String);
final aes = _initCipher(false, derivedKey, iv);
final privateKey =
Base58Encoder.instance.encode(aes.process(encryptedPrivateKey));
final id = parseUuid(data['id'] as String);
return KeyStore._(privateKey, derivator, encodedPassword, iv, id);
}