Skip to content

Commit

Permalink
CW-711 passphrase for XMR/WOWcreation (#1992)
Browse files Browse the repository at this point in the history
* add monero passphrase
add wownero passphrase
add passphrase to seed screen

* obscure passphrase by default
disable passphrase create for zano

* Update lib/view_model/wallet_keys_view_model.dart [skip ci]

* Update lib/src/screens/wallet_keys/wallet_keys_page.dart [skip ci]

* Update lib/view_model/advanced_privacy_settings_view_model.dart

* dynamic passphrase icon

* fix polyseed not being encrypted by passphrase

---------

Co-authored-by: Omar Hatem <[email protected]>
  • Loading branch information
MrCyjaneK and OmarHatem28 authored Feb 1, 2025
1 parent 96921d5 commit 8b56c52
Show file tree
Hide file tree
Showing 15 changed files with 138 additions and 20 deletions.
7 changes: 3 additions & 4 deletions cw_monero/lib/api/wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,11 @@ String getSeed() {
if (cakepolyseed != "") {
if (cakepassphrase != "") {
try {
final lang = PolyseedLang.getByPhrase(cakepassphrase);
final lang = PolyseedLang.getByPhrase(cakepolyseed);
final coin = PolyseedCoin.POLYSEED_MONERO;
final ps = Polyseed.decode(cakepolyseed, lang, coin);
final passphrase = getPassphrase();
if (ps.isEncrypted || passphrase == "") return ps.encode(lang, coin);
ps.crypt(getPassphrase());
if (ps.isEncrypted || cakepassphrase == "") return ps.encode(lang, coin);
ps.crypt(cakepassphrase);
return ps.encode(lang, coin);
} catch (e) {
printV(e);
Expand Down
7 changes: 6 additions & 1 deletion cw_monero/lib/api/wallet_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void createWalletSync(
{required String path,
required String password,
required String language,
required String passphrase,
int nettype = 0}) {
txhistory = null;
final newWptr = monero.WalletManager_createWallet(wmPtr,
Expand All @@ -80,6 +81,7 @@ void createWalletSync(
throw WalletCreationException(message: monero.Wallet_errorString(newWptr));
}
wptr = newWptr;
monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase);
monero.Wallet_store(wptr!, path: path);
openedWalletsByPath[path] = wptr!;
_lastOpenedWallet = path;
Expand Down Expand Up @@ -390,8 +392,9 @@ void _createWallet(Map<String, dynamic> args) {
final path = args['path'] as String;
final password = args['password'] as String;
final language = args['language'] as String;
final passphrase = args['passphrase'] as String;

createWalletSync(path: path, password: password, language: language);
createWalletSync(path: path, password: password, language: language, passphrase: passphrase);
}

void _restoreFromSeed(Map<String, dynamic> args) {
Expand Down Expand Up @@ -459,11 +462,13 @@ Future<void> createWallet(
{required String path,
required String password,
required String language,
required String passphrase,
int nettype = 0}) async =>
_createWallet({
'path': path,
'password': password,
'language': language,
'passphrase': passphrase,
'nettype': nettype
});

Expand Down
2 changes: 1 addition & 1 deletion cw_monero/lib/monero_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
passphrase: monero_wallet.getPassphrase());

int? get restoreHeight =>
transactionHistory.transactions.values.firstOrNull?.height;
transactionHistory.transactions.values.firstOrNull?.height ?? monero.Wallet_getRefreshFromBlockHeight(wptr!);

monero_wallet.SyncListener? _listener;
ReactionDisposer? _onAccountChangeReaction;
Expand Down
11 changes: 8 additions & 3 deletions cw_monero/lib/monero_wallet_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import 'package:polyseed/polyseed.dart';

class MoneroNewWalletCredentials extends WalletCredentials {
MoneroNewWalletCredentials(
{required String name, required this.language, required this.isPolyseed, String? password})
{required String name, required this.language, required this.isPolyseed, String? password, this.passphrase})
: super(name: name, password: password);

final String language;
final bool isPolyseed;
final String? passphrase;
}

class MoneroRestoreWalletFromHardwareCredentials extends WalletCredentials {
Expand Down Expand Up @@ -92,7 +93,7 @@ class MoneroWalletService extends WalletService<
@override
WalletType getType() => WalletType.monero;

@override
@override
Future<MoneroWallet> create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async {
try {
final path = await pathForWallet(name: credentials.name, type: getType());
Expand All @@ -112,7 +113,7 @@ class MoneroWalletService extends WalletService<
}

await monero_wallet_manager.createWallet(
path: path, password: credentials.password!, language: credentials.language);
path: path, password: credentials.password!, language: credentials.language, passphrase: credentials.passphrase??"");
final wallet = MoneroWallet(
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource,
Expand Down Expand Up @@ -382,6 +383,10 @@ class MoneroWalletService extends WalletService<
restoreHeight: height,
spendKey: spendKey);


monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase??'');

final wallet = MoneroWallet(
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
Expand Down
2 changes: 1 addition & 1 deletion cw_wownero/lib/api/wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ String getSeed() {
if (cakepolyseed != "") {
if (cakepassphrase != "") {
try {
final lang = PolyseedLang.getByPhrase(cakepassphrase);
final lang = PolyseedLang.getByPhrase(cakepolyseed);
final coin = PolyseedCoin.POLYSEED_WOWNERO;
final ps = Polyseed.decode(cakepolyseed, lang, coin);
final passphrase = getPassphrase();
Expand Down
8 changes: 7 additions & 1 deletion cw_wownero/lib/api/wallet_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ void createWalletSync(
{required String path,
required String password,
required String language,
required String passphrase,
int nettype = 0}) {
txhistory = null;
final newWptr = wownero.WalletManager_createWallet(wmPtr,
Expand All @@ -76,6 +77,8 @@ void createWalletSync(
throw WalletCreationException(message: wownero.Wallet_errorString(newWptr));
}
wptr = newWptr;
wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase);

wownero.Wallet_store(wptr!, path: path);
openedWalletsByPath[path] = wptr!;

Expand Down Expand Up @@ -362,8 +365,9 @@ void _createWallet(Map<String, dynamic> args) {
final path = args['path'] as String;
final password = args['password'] as String;
final language = args['language'] as String;
final passphrase = args['passphrase'] as String;

createWalletSync(path: path, password: password, language: language);
createWalletSync(path: path, password: password, language: language, passphrase: passphrase);
}

void _restoreFromSeed(Map<String, dynamic> args) {
Expand Down Expand Up @@ -431,11 +435,13 @@ Future<void> createWallet(
{required String path,
required String password,
required String language,
required String passphrase,
int nettype = 0}) async =>
_createWallet({
'path': path,
'password': password,
'language': language,
'passphrase': passphrase,
'nettype': nettype
});

Expand Down
5 changes: 5 additions & 0 deletions cw_wownero/lib/wownero_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wownero_amount_format.dart';
import 'package:cw_core/wownero_balance.dart';
import 'package:cw_wownero/api/account_list.dart';
import 'package:cw_wownero/api/coins_info.dart';
import 'package:cw_wownero/api/structs/pending_transaction.dart';
import 'package:cw_wownero/api/transaction_history.dart' as transaction_history;
Expand Down Expand Up @@ -131,6 +132,10 @@ abstract class WowneroWalletBase
publicViewKey: wownero_wallet.getPublicViewKey(),
passphrase: wownero_wallet.getPassphrase());

int? get restoreHeight =>
transactionHistory.transactions.values.firstOrNull?.height ?? wownero.Wallet_getRefreshFromBlockHeight(wptr!);


wownero_wallet.SyncListener? _listener;
ReactionDisposer? _onAccountChangeReaction;
ReactionDisposer? _onTxHistoryChangeReaction;
Expand Down
9 changes: 7 additions & 2 deletions cw_wownero/lib/wownero_wallet_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_core/get_height_by_date.dart';
import 'package:cw_wownero/api/account_list.dart';
import 'package:cw_wownero/api/exceptions/wallet_opening_exception.dart';
import 'package:cw_wownero/api/wallet_manager.dart' as wownero_wallet_manager;
import 'package:cw_wownero/api/wallet_manager.dart';
Expand All @@ -21,11 +22,12 @@ import 'package:monero/wownero.dart' as wownero;

class WowneroNewWalletCredentials extends WalletCredentials {
WowneroNewWalletCredentials(
{required String name, required this.language, required this.isPolyseed, String? password})
{required String name, required this.language, required this.isPolyseed, this.passphrase, String? password})
: super(name: name, password: password);

final String language;
final bool isPolyseed;
final String? passphrase;
}

class WowneroRestoreWalletFromSeedCredentials extends WalletCredentials {
Expand Down Expand Up @@ -95,7 +97,7 @@ class WowneroWalletService extends WalletService<
}

await wownero_wallet_manager.createWallet(
path: path, password: credentials.password!, language: credentials.language);
path: path, password: credentials.password!, language: credentials.language, passphrase: credentials.passphrase??'');
final wallet = WowneroWallet(
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
await wallet.init();
Expand Down Expand Up @@ -345,6 +347,9 @@ class WowneroWalletService extends WalletService<
restoreHeight: height,
spendKey: spendKey);

wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase??'');

final wallet = WowneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, password: password);
await wallet.init();

Expand Down
3 changes: 2 additions & 1 deletion lib/monero/cw_monero.dart
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,10 @@ class CWMonero extends Monero {
required String name,
required String language,
required bool isPolyseed,
required String? passphrase,
String? password}) =>
MoneroNewWalletCredentials(
name: name, password: password, language: language, isPolyseed: isPolyseed);
name: name, password: password, language: language, isPolyseed: isPolyseed, passphrase: passphrase);

@override
Map<String, String> getKeys(Object wallet) {
Expand Down
64 changes: 64 additions & 0 deletions lib/src/screens/wallet_keys/wallet_keys_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:cake_wallet/entities/qr_view_data.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
Expand All @@ -15,6 +17,8 @@ import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/view_model/wallet_keys_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
import 'package:qr_flutter/qr_flutter.dart';

class WalletKeysPage extends BasePage {
Expand Down Expand Up @@ -162,6 +166,8 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
children: [
if (isLegacySeedOnly || isLegacySeed) _buildHeightBox(),
const SizedBox(height: 20),
(_buildPassphraseBox() ?? Container()),
if (widget.walletKeysViewModel.passphrase.isNotEmpty) const SizedBox(height: 20),
Expanded(
child: SeedPhraseGridWidget(
list: isLegacySeed
Expand Down Expand Up @@ -262,6 +268,64 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
),
);
}


Widget? _buildPassphraseBox() {
if (widget.walletKeysViewModel.passphrase.isEmpty) return null;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 14),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context).cardColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
S.of(context).passphrase_view_keys,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor.withOpacity(0.5),
),
),
const SizedBox(width: 6),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Observer(builder: (BuildContext context) {
return Text(
(widget.walletKeysViewModel.obscurePassphrase) ?
"*****" :
widget.walletKeysViewModel.passphrase,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
),
);
}),
Observer(builder: (BuildContext context) {
return GestureDetector(
onTap: () {
widget.walletKeysViewModel.obscurePassphrase = !widget.walletKeysViewModel.obscurePassphrase;
},
child: Icon(
widget.walletKeysViewModel.obscurePassphrase ? Icons.visibility_off : Icons.visibility,
size: 16,
color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.7),
)
);
}),
],
),
),
],
),
);
}


Widget _buildBottomActionPanel({
Expand Down
4 changes: 2 additions & 2 deletions lib/view_model/advanced_privacy_settings_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
WalletType.ethereum,
WalletType.polygon,
WalletType.tron,
if (isRestore) WalletType.monero,
if (isRestore) WalletType.wownero,
WalletType.monero,
WalletType.wownero,
if (isRestore) WalletType.zano,
].contains(type);

Expand Down
18 changes: 18 additions & 0 deletions lib/view_model/wallet_keys_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,21 @@ abstract class WalletKeysViewModelBase with Store {
if (_wallet.type == WalletType.monero) {
return monero!.getRestoreHeight(_wallet)?.toString() ?? '';
}
if (_wallet.type == WalletType.wownero) {
return wownero!.getRestoreHeight(_wallet)?.toString() ?? '';
}
return '';
}



@observable
bool obscurePassphrase = true;

String get passphrase {
return _wallet.passphrase ?? '';
}

/// The Regex split the words based on any whitespace character.
///
/// Either standard ASCII space (U+0020) or the full-width space character (U+3000) used by the Japanese.
Expand Down Expand Up @@ -309,6 +321,12 @@ abstract class WalletKeysViewModelBase with Store {
}

Future<String?> get restoreHeight async {
if (_wallet.type == WalletType.monero) {
return monero!.getRestoreHeight(_wallet)?.toString();
}
if (_wallet.type == WalletType.wownero) {
return wownero!.getRestoreHeight(_wallet)?.toString();
}
if (_restoreHeightByTransactions != 0)
return getRoundedRestoreHeight(_restoreHeightByTransactions);
if (_restoreHeight != 0) return _restoreHeight.toString();
Expand Down
2 changes: 2 additions & 0 deletions lib/view_model/wallet_new_vm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
name: name,
language: options!.first as String,
password: walletPassword,
passphrase: passphrase,
isPolyseed: options.last as bool);
case WalletType.bitcoin:
case WalletType.litecoin:
Expand Down Expand Up @@ -168,6 +169,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
language: options!.first as String,
isPolyseed: options.last as bool,
password: walletPassword,
passphrase: passphrase,
);
case WalletType.zano:
return zano!.createZanoNewWalletCredentials(
Expand Down
Loading

0 comments on commit 8b56c52

Please sign in to comment.