CakeWallet/cw_monero/lib/bip39_seed.dart

60 lines
1.7 KiB
Dart
Raw Permalink Normal View History

CW-723-Add-Monero-support-to-the-Shared-Seed-feature-in-Cake (#2131) * feat: add exodus style bip39 to monero legacy seed * feat: restore monero wallet from bip39 and add test * bug: fix wrong naming in CI * feat: add monero bip39 UI flow * fix: monero.dart generation * fix: skip monero_wallet_service tests till CI is fixed * ci: copy monero_libwallet2_api_c.so to /usr/lib for testing ci: reduce timeout for cw_monero tests * fix: monero wallet creation credentials default to bip39 if mnemonic are set * fix: do not skip monero wallets services test * fix: Include non bip39 monero wallets on Wallet Group * fix: null pointer stemming from missing language selector if seed is selected * fix: Fixes to Bip39 Creation and restore - Do not restore from 0 for fresh bip39 wallet - disallow restoring bip39 wallet without date or height * fix: Fixes to Bip39 restore - Refresh height is now getting set correctly - Add new create monero wallet tests - Add seed-language English for Bip39 Monero wallets - Fix seed-type naming * feat (cw_monero): Store monero wallet after bip39 creation * feat (cw_monero): remove prints from monero_wallet_service_test.dart * fix: exception during seed language autodetect * feat (cw_monero): Add support for passphrases on bip39 seeds * feat (cw_monero): Add support for passphrases on bip39 seeds * fix: seed language selection for recovering bip39 wallets * style: improve readability of isLegacySeedOnly in wallet_keys_view_model.dart * feat: hide monero seed type selector from advanced settings when creating a child wallet * fix(cw_monero): use named arguments for bip39_seed tests --------- Co-authored-by: cyan <cyjan@mrcyjanek.net>
2025-04-10 03:31:26 +02:00
import 'dart:typed_data';
import 'package:bip32/bip32.dart' as bip32;
import 'package:bip39/bip39.dart' as bip39;
import 'package:polyseed/polyseed.dart';
bool isBip39Seed(String mnemonic) => bip39.validateMnemonic(mnemonic);
String getBip39Seed() => bip39.generateMnemonic();
String getLegacySeedFromBip39(String mnemonic,
{int accountIndex = 0, String passphrase = ""}) {
final seed = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase);
final bip32KeyPair =
bip32.BIP32.fromSeed(seed).derivePath("m/44'/128'/$accountIndex'/0/0");
final spendKey = _reduceECKey(bip32KeyPair.privateKey!);
return LegacySeedLang.getByEnglishName("English")
.encodePhrase(spendKey.toHexString());
}
const _ed25519CurveOrder =
"1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
Uint8List _reduceECKey(Uint8List buffer) {
final curveOrder = BigInt.parse(_ed25519CurveOrder, radix: 16);
final bigNumber = _readBytes(buffer);
var result = bigNumber % curveOrder;
final resultBuffer = Uint8List(32);
for (var i = 0; i < 32; i++) {
resultBuffer[i] = (result & BigInt.from(0xff)).toInt();
result = result >> 8;
}
return resultBuffer;
}
/// Read BigInt from a little-endian Uint8List
/// From https://github.com/dart-lang/sdk/issues/32803#issuecomment-387405784
BigInt _readBytes(Uint8List bytes) {
BigInt read(int start, int end) {
if (end - start <= 4) {
var result = 0;
for (int i = end - 1; i >= start; i--) {
result = result * 256 + bytes[i];
}
return BigInt.from(result);
}
final mid = start + ((end - start) >> 1);
return read(start, mid) +
read(mid, end) * (BigInt.one << ((mid - start) * 8));
}
return read(0, bytes.length);
}