mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-11 13:24:51 +00:00
pin migration, part 1
This commit is contained in:
parent
fc6be2aa97
commit
0746687efc
5 changed files with 44 additions and 29 deletions
|
@ -39,13 +39,13 @@ class AuthService with Store {
|
|||
|
||||
Future<void> setPassword(String password) async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPassword = encodedPinCode(pin: password);
|
||||
final hashedPassword = await argon2Hash(password: password);
|
||||
// secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless
|
||||
// we delete what's there first:
|
||||
if (Platform.isMacOS) {
|
||||
await secureStorage.delete(key: key);
|
||||
}
|
||||
await secureStorage.write(key: key, value: encodedPassword);
|
||||
await secureStorage.write(key: key, value: hashedPassword);
|
||||
}
|
||||
|
||||
Future<bool> canAuthenticate() async {
|
||||
|
@ -64,10 +64,8 @@ class AuthService with Store {
|
|||
|
||||
Future<bool> authenticate(String pin) async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPin = await secureStorage.read(key: key);
|
||||
final decodedPin = decodedPinCode(pin: encodedPin!);
|
||||
|
||||
return decodedPin == pin;
|
||||
final hashedPassword = await secureStorage.read(key: key);
|
||||
return verifyArgon2Hash(password: pin, hash: hashedPassword!);
|
||||
}
|
||||
|
||||
void saveLastAuthTime() {
|
||||
|
|
|
@ -445,7 +445,7 @@ class BackupService {
|
|||
});
|
||||
|
||||
await _flutterSecureStorage.delete(key: pinCodeKey);
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: (await argon2Hash(password: decodedPin)));
|
||||
|
||||
keychainDumpFile.deleteSync();
|
||||
}
|
||||
|
@ -473,7 +473,7 @@ class BackupService {
|
|||
});
|
||||
|
||||
await _flutterSecureStorage.delete(key: pinCodeKey);
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: (await argon2Hash(password: decodedPin)));
|
||||
|
||||
keychainDumpFile.deleteSync();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:io' show Directory, File, Platform;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/encrypt.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||
|
@ -187,6 +188,7 @@ Future<void> defaultSettingsMigration(
|
|||
break;
|
||||
case 26:
|
||||
await pinEncryptionMigration(secureStorage: secureStorage);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -384,24 +386,32 @@ Future<void> pinEncryptionMigration({required FlutterSecureStorage secureStorage
|
|||
try {
|
||||
// first, get the encoded pin:
|
||||
final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
String? encodedPin;
|
||||
encodedPin = await secureStorage.read(key: keyForPinCode);
|
||||
String? encodedPin = await secureStorage.read(key: keyForPinCode);
|
||||
|
||||
// if (encodedPin == null) {
|
||||
// return;
|
||||
// }
|
||||
// we don't have a pin?!?
|
||||
if (encodedPin == null) {
|
||||
print("pinEncryptionMigration: no pin found in secure storage!");
|
||||
// this should never happen, but just in case let's just set the pin to "0000"
|
||||
// as it's better than permanently locking the user out with an un-decryptable pin
|
||||
encodedPin = encodedPinCode(pin: "0000");
|
||||
}
|
||||
|
||||
// // ensure we overwrite by deleting the old key first:
|
||||
// await secureStorage.delete(key: keyForPinCode);
|
||||
// await secureStorage.write(
|
||||
// key: keyForPinCode,
|
||||
// value: encodedPin,
|
||||
// iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
// mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
// );
|
||||
// decode & re-encode the pin:
|
||||
final decodedPin = decodedPinCode(pin: encodedPin);
|
||||
final hashedPin = await argon2Hash(password: decodedPin);
|
||||
|
||||
// ensure we overwrite by deleting the old key first:
|
||||
await secureStorage.delete(key: keyForPinCode);
|
||||
// write the new argon2 hashed pin:
|
||||
await secureStorage.write(
|
||||
key: keyForPinCode,
|
||||
value: hashedPin,
|
||||
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
);
|
||||
} catch (e) {
|
||||
// failure isn't really an option since we'll be updating how pins are stored and used
|
||||
print(e);
|
||||
print("pinEncryptionMigration: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
import 'package:encrypt/encrypt.dart';
|
||||
// import 'package:password/password.dart';
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
import 'package:dargon2_flutter/dargon2_flutter.dart';
|
||||
|
||||
Future<String> argon2Hash({required String password}) async {
|
||||
final result = await argon2.hashPasswordString(password, salt: Salt.newSalt());
|
||||
// the salt is stored within the encoded string:
|
||||
return result.encodedString;
|
||||
}
|
||||
|
||||
Future<bool> verifyArgon2Hash({required String password, required String hash}) async {
|
||||
return argon2.verifyHashString(password, hash);
|
||||
}
|
||||
|
||||
// @@@@@@@@@@@@@@@ OLD (kept for reference purposes, do not use!) @@@@@@@@@@@@@
|
||||
|
||||
String encrypt({required String source, required String key}) {
|
||||
final _key = Key.fromUtf8(key);
|
||||
final iv = IV.allZerosOfLength(16);
|
||||
final encrypter = Encrypter(AES(_key));
|
||||
final encrypted = encrypter.encrypt(source, iv: iv);
|
||||
|
||||
return encrypted.base64;
|
||||
}
|
||||
|
||||
|
@ -16,7 +28,6 @@ String decrypt({required String source, required String key}) {
|
|||
final iv = IV.allZerosOfLength(16);
|
||||
final encrypter = Encrypter(AES(_key));
|
||||
final decrypted = encrypter.decrypt64(source, iv: iv);
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
|
@ -31,26 +42,22 @@ String hash({required String source}) {
|
|||
|
||||
String encodedPinCode({required String pin}) {
|
||||
final source = '${secrets.salt}$pin';
|
||||
|
||||
return encrypt(source: source, key: secrets.key);
|
||||
}
|
||||
|
||||
String decodedPinCode({required String pin}) {
|
||||
final decrypted = decrypt(source: pin, key: secrets.key);
|
||||
|
||||
return decrypted.substring(secrets.key.length, decrypted.length);
|
||||
}
|
||||
|
||||
String encodeWalletPassword({required String password}) {
|
||||
final source = password;
|
||||
final _key = secrets.shortKey + secrets.walletSalt;
|
||||
|
||||
return encrypt(source: source, key: _key);
|
||||
}
|
||||
|
||||
String decodeWalletPassword({required String password}) {
|
||||
final source = password;
|
||||
final _key = secrets.shortKey + secrets.walletSalt;
|
||||
|
||||
return decrypt(source: source, key: _key);
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ Future<void> initializeAppConfigs() async {
|
|||
transactionDescriptions: transactionDescriptions,
|
||||
secureStorage: secureStorage,
|
||||
anonpayInvoiceInfo: anonpayInvoiceInfo,
|
||||
initialMigrationVersion: 25);
|
||||
initialMigrationVersion: 26);
|
||||
}
|
||||
|
||||
Future<void> initialSetup(
|
||||
|
|
Loading…
Reference in a new issue