Changed random seed generation for bitcoin.

This commit is contained in:
M 2021-05-10 13:06:57 +03:00
parent d23228ac01
commit bcd4fdd5e0
23 changed files with 116 additions and 56 deletions

View file

@ -1,15 +1,49 @@
package com.cakewallet.cake_wallet;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import java.security.SecureRandom;
public class MainActivity extends FlutterFragmentActivity {
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel utilsChannel =
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
UTILS_CHANNEL);
utilsChannel.setMethodCallHandler(this::handle);
}
private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
Handler handler = new Handler(Looper.getMainLooper());
try {
if (call.method.equals("sec_random")) {
int count = call.argument("count");
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[count];
random.nextBytes(bytes);
handler.post(() -> result.success(bytes));
} else {
handler.post(() -> result.notImplemented());
}
} catch (Exception e) {
handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null));
}
}
}

View file

@ -1,13 +0,0 @@
package com.cakewallet.cake_wallet
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine){
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
}

View file

@ -0,0 +1,12 @@
import Foundation
func secRandom(count: Int) -> Data? {
var bytes = [Int8](repeating: 0, count: count)
let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
if status == errSecSuccess {
return Data(bytes: bytes, count: bytes.count)
}
return nil
}

View file

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C44A7192518EF8000B570ED /* decrypt.swift */; };
0C9D68C9264854B60011B691 /* secRandom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9D68C8264854B60011B691 /* secRandom.swift */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
20ED0868E1BD7E12278C0CB3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
@ -21,6 +22,7 @@
0C400E0F25B21ABB0025E469 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
0C44A7192518EF8000B570ED /* decrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = decrypt.swift; sourceTree = "<group>"; };
0C9986A3251A932F00D566FD /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0C9D68C8264854B60011B691 /* secRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = secRandom.swift; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
20F67A1B2C2FCB2A3BB048C1 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
@ -65,6 +67,7 @@
isa = PBXGroup;
children = (
0C44A7192518EF8000B570ED /* decrypt.swift */,
0C9D68C8264854B60011B691 /* secRandom.swift */,
);
path = CakeWallet;
sourceTree = "<group>";
@ -274,6 +277,7 @@
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
0C9D68C9264854B60011B691 /* secRandom.swift in Sources */,
0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -358,7 +362,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 35;
CURRENT_PROJECT_VERSION = 36;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -375,7 +379,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.1.6;
MARKETING_VERSION = 4.1.7;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -501,7 +505,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 35;
CURRENT_PROJECT_VERSION = 36;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -518,7 +522,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.1.6;
MARKETING_VERSION = 4.1.7;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -536,7 +540,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 35;
CURRENT_PROJECT_VERSION = 36;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -553,7 +557,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.1.6;
MARKETING_VERSION = 4.1.7;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View file

@ -8,9 +8,10 @@ import Flutter
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.cakewallet.cakewallet/legacy_wallet_migration",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
let legacyMigrationChannel = FlutterMethodChannel(
name: "com.cakewallet.cakewallet/legacy_wallet_migration",
binaryMessenger: controller.binaryMessenger)
legacyMigrationChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
switch call.method {
@ -52,6 +53,24 @@ import Flutter
}
})
let utilsChannel = FlutterMethodChannel(
name: "com.cake_wallet/native_utils",
binaryMessenger: controller.binaryMessenger)
utilsChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
switch call.method {
case "sec_random":
guard let args = call.arguments as? Dictionary<String, Any>,
let count = args["count"] as? Int else {
result(nil)
return
}
result(secRandom(count: count))
default:
result(FlutterMethodNotImplemented)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

View file

@ -4,23 +4,11 @@ import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:unorm_dart/unorm_dart.dart' as unorm;
import 'package:cryptography/cryptography.dart' as cryptography;
import 'package:cake_wallet/core/sec_random_native.dart';
const segwit = '100';
final wordlist = englishWordlist;
Uint8List randomBytes(int length, {bool secure = false}) {
assert(length > 0);
final random = secure ? Random.secure() : Random();
final ret = Uint8List(length);
for (var i = 0; i < length; i++) {
ret[i] = random.nextInt(256);
}
return ret;
}
double logBase(num x, num base) => log(x) / log(base);
String mnemonicEncode(int i) {
@ -102,14 +90,15 @@ List<bool> prefixMatches(String source, List<String> prefixes) {
return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList();
}
String generateMnemonic({int strength = 132, String prefix = segwit}) {
Future<String> generateMnemonic(
{int strength = 264, String prefix = segwit}) async {
final wordBitlen = logBase(wordlist.length, 2).ceil();
final wordCount = strength / wordBitlen;
final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil();
var result = '';
do {
final bytes = randomBytes(byteCount);
final bytes = await secRandom(byteCount);
maskBytes(bytes, strength);
result = encode(bytes);
} while (!prefixMatches(result, [prefix]).first);
@ -134,7 +123,7 @@ bool matchesAnyPrefix(String mnemonic) =>
bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
try {
return matchesAnyPrefix(mnemonic);
} catch(e) {
} catch (e) {
return false;
}
}

View file

@ -1,5 +1,5 @@
class BitcoinMnemonicIsIncorrectException implements Exception {
@override
String toString() =>
'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 words separated by space.';
'Bitcoin mnemonic has incorrect format. Mnemonic should contain 24 words separated by space.';
}

View file

@ -25,7 +25,7 @@ class BitcoinWalletService extends WalletService<
type: WalletType.bitcoin, name: credentials.name);
final wallet = BitcoinWalletBase.build(
dirPath: dirPath,
mnemonic: generateMnemonic(),
mnemonic: await generateMnemonic(),
password: credentials.password,
name: credentials.name,
walletInfo: credentials.walletInfo);
@ -47,7 +47,7 @@ class BitcoinWalletService extends WalletService<
final walletPath = '$walletDirPath/$name';
final walletJSONRaw = await read(path: walletPath, password: password);
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
(info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
orElse: () => null);
final wallet = BitcoinWalletBase.fromJSON(
password: password,

View file

@ -0,0 +1,13 @@
import 'dart:typed_data';
import 'package:flutter/services.dart';
const utils = const MethodChannel('com.cake_wallet/native_utils');
Future<Uint8List> secRandom(int count) async {
try {
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count});
} on PlatformException catch (_) {
return Uint8List.fromList([]);
}
}

View file

@ -228,7 +228,7 @@ class MoneroWalletService extends WalletService<
final name = f.path.split('/').last;
final newPath = newWalletDirPath + '/$name';
final newFile = File(newPath);
print(file.path);
if (!newFile.existsSync()) {
newFile.createSync();
}

View file

@ -13,7 +13,7 @@ class PreSeedPage extends BasePage {
imageDark = Image.asset('assets/images/pre_seed_dark.png'),
wordsCount = type == WalletType.monero
? 25
: 12; // FIXME: Stupid fast implementation
: 24; // FIXME: Stupid fast implementation
final Image imageDark;
final Image imageLight;
@ -49,7 +49,9 @@ class PreSeedPage extends BasePage {
Padding(
padding: EdgeInsets.only(top: 70, left: 16, right: 16),
child: Text(
S.of(context).pre_seed_description(wordsCount.toString()),
S
.of(context)
.pre_seed_description(wordsCount.toString()),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,

View file

@ -11,7 +11,7 @@ description: Cake Wallet.
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 4.1.6+45
version: 4.1.7+46
environment:
sdk: ">=2.7.0 <3.0.0"

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Beschreibung zur Wiederherstellung der Brieftasche",
"restore_new_seed" : "Neuer Seed",
"restore_active_seed" : "Aktives Seed",
"restore_bitcoin_description_from_seed" : "Stellen Sie Ihre Brieftasche aus dem 12-Wort-Kombinationscode wieder her",
"restore_bitcoin_description_from_seed" : "Stellen Sie Ihre Brieftasche aus dem 24-Wort-Kombinationscode wieder her",
"restore_bitcoin_description_from_keys" : "Stellen Sie Ihre Brieftasche aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her",
"restore_bitcoin_title_from_keys" : "Aus WIF wiederherstellen",
"restore_from_date_or_blockheight" : "Bitte geben Sie einige Tage vor dem Erstellen dieser Brieftasche ein Datum ein. Oder wenn Sie die Blockhöhe kennen, geben Sie sie stattdessen ein",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Restaurar billetera",
"restore_new_seed" : "Nueva semilla",
"restore_active_seed" : "Semilla activa",
"restore_bitcoin_description_from_seed" : "Restaure su billetera a partir del código de combinación de 12 palabras",
"restore_bitcoin_description_from_seed" : "Restaure su billetera a partir del código de combinación de 24 palabras",
"restore_bitcoin_description_from_keys" : "Restaure su billetera a partir de una cadena WIF generada a partir de sus claves privadas",
"restore_bitcoin_title_from_keys" : "Restaurar desde WIF",
"restore_from_date_or_blockheight" : "Ingrese una fecha unos días antes de crear esta billetera. O si conoce la altura del bloque, ingréselo en su lugar",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "बटुआ विवरण पुनर्स्थापित करें",
"restore_new_seed" : "नया बीज",
"restore_active_seed" : "सक्रिय बीज",
"restore_bitcoin_description_from_seed" : "12 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें",
"restore_bitcoin_description_from_seed" : "24 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें",
"restore_bitcoin_description_from_keys" : "अपने निजी कुंजी से उत्पन्न WIF स्ट्रिंग से अपने वॉलेट को पुनर्स्थापित करें",
"restore_bitcoin_title_from_keys" : "WIF से पुनर्स्थापित करें",
"restore_from_date_or_blockheight" : "कृपया इस वॉलेट को बनाने से कुछ दिन पहले एक तारीख दर्ज करें। या यदि आप ब्लॉकचेट जानते हैं, तो कृपया इसके बजाय इसे दर्ज करें",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "ウォレットの復元",
"restore_new_seed" : "新しい種",
"restore_active_seed" : "アクティブシード",
"restore_bitcoin_description_from_seed" : "12ワードの組み合わせコードからウォレットを復元する",
"restore_bitcoin_description_from_seed" : "24ワードの組み合わせコードからウォレットを復元する",
"restore_bitcoin_description_from_keys" : "秘密鍵から生成されたWIF文字列からウォレットを復元します",
"restore_bitcoin_title_from_keys" : "WIFから復元",
"restore_from_date_or_blockheight" : "このウォレットを作成する数日前に日付を入力してください。 または、ブロックの高さがわかっている場合は、代わりに入力してください",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "월렛 복원 설명",
"restore_new_seed" : "새로운 씨앗",
"restore_active_seed" : "활성 종자",
"restore_bitcoin_description_from_seed" : "12 단어 조합 코드에서 지갑 복원",
"restore_bitcoin_description_from_seed" : "24 단어 조합 코드에서 지갑 복원",
"restore_bitcoin_description_from_keys" : "개인 키에서 생성 된 WIF 문자열에서 지갑 복원",
"restore_bitcoin_title_from_keys" : "WIF에서 복원",
"restore_from_date_or_blockheight" : "이 지갑을 생성하기 며칠 전에 날짜를 입력하십시오. 또는 블록 높이를 알고있는 경우 대신 입력하십시오.",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Portemonnee-herstelbeschrijving",
"restore_new_seed" : "Nieuw zaad",
"restore_active_seed" : "Actief zaad",
"restore_bitcoin_description_from_seed" : "Herstel uw portemonnee met een combinatiecode van 12 woorden",
"restore_bitcoin_description_from_seed" : "Herstel uw portemonnee met een combinatiecode van 24 woorden",
"restore_bitcoin_description_from_keys" : "Herstel uw portemonnee van de gegenereerde WIF-string van uw privésleutels",
"restore_bitcoin_title_from_keys" : "Herstel van WIF",
"restore_from_date_or_blockheight" : "Voer een datum in een paar dagen voordat u deze portemonnee heeft gemaakt. Of als u de blokhoogte kent, voert u deze in",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Opis przywracania portfela",
"restore_new_seed" : "Nowe nasienie",
"restore_active_seed" : "Aktywne nasiona",
"restore_bitcoin_description_from_seed" : "Przywróć swój portfel z kodu złożonego z 12 słów",
"restore_bitcoin_description_from_seed" : "Przywróć swój portfel z kodu złożonego z 24 słów",
"restore_bitcoin_description_from_keys" : "Przywróć swój portfel z wygenerowanego ciągu WIF z kluczy prywatnych",
"restore_bitcoin_title_from_keys" : "Przywróć z WIF",
"restore_from_date_or_blockheight" : "Wprowadź datę na kilka dni przed utworzeniem tego portfela. Lub jeśli znasz wysokość bloku, wprowadź go zamiast tego",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Restauração da carteira",
"restore_new_seed" : "Nova semente",
"restore_active_seed" : "Semente ativa",
"restore_bitcoin_description_from_seed" : "Restaure sua carteira a partir de um código de combinação de 12 palavras",
"restore_bitcoin_description_from_seed" : "Restaure sua carteira a partir de um código de combinação de 24 palavras",
"restore_bitcoin_description_from_keys" : "Restaure sua carteira a partir da string WIF gerada de suas chaves privadas",
"restore_bitcoin_title_from_keys" : "Restaurar de WIF",
"restore_from_date_or_blockheight" : "Insira uma data alguns dias antes de criar esta carteira. Ou se você souber a altura do bloco, insira-o",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Описание восстановления кошелька",
"restore_new_seed" : "Новая мнемоническая фраза",
"restore_active_seed" : "Активная мнемоническая фраза",
"restore_bitcoin_description_from_seed" : "Вы можете восстановить кошелёк используя 12-ти значную мнемоническую фразу",
"restore_bitcoin_description_from_seed" : "Вы можете восстановить кошелёк используя 24-ти значную мнемоническую фразу",
"restore_bitcoin_description_from_keys" : "Вы можете восстановить кошелёк с помощью WIF",
"restore_bitcoin_title_from_keys" : "Восстановить с помощью WIF",
"restore_from_date_or_blockheight" : "Пожалуйста, введите дату за несколько дней до создания этого кошелька. Или, если вы знаете высоту блока, введите ее значение",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "Опис відновлюваного гаманця",
"restore_new_seed" : "Нова мнемонічна фраза",
"restore_active_seed" : "Активна мнемонічна фраза",
"restore_bitcoin_description_from_seed" : "Ви можете відновити гаманець використовуючи 12-ти слівну мнемонічну фразу",
"restore_bitcoin_description_from_seed" : "Ви можете відновити гаманець використовуючи 24-ти слівну мнемонічну фразу",
"restore_bitcoin_description_from_keys" : "Ви можете відновити гаманець за допомогою WIF",
"restore_bitcoin_title_from_keys" : "Відновити за допомогою WIF",
"restore_from_date_or_blockheight" : "Будь ласка, введіть дату за кілька днів до створення цього гаманця. Або, якщо ви знаєте висоту блоку, введіть її значення",

View file

@ -170,7 +170,7 @@
"restore_wallet_restore_description" : "钱包还原说明",
"restore_new_seed" : "新種子",
"restore_active_seed" : "活性種子",
"restore_bitcoin_description_from_seed" : "從12個單詞的組合碼恢復您的錢包",
"restore_bitcoin_description_from_seed" : "從24個單詞的組合碼恢復您的錢包",
"restore_bitcoin_description_from_keys" : "從私鑰中生成的WIF字符串還原您的錢包",
"restore_bitcoin_title_from_keys" : "從WIF還原",
"restore_from_date_or_blockheight" : "請在創建此錢包之前幾天輸入一個日期。 或者,如果您知道塊高,請改為輸入",