Changed random seed generation for bitcoin.

M committed May 10, 2021 at 13:06 UTC bcd4fdd5e07800f922403995e772b8d285cf3917
23 files changed +116 -56
android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java
+34
@@ -1,15 +1,49 @@
1 package com.cakewallet.cake_wallet;
2
3 import androidx.annotation.NonNull;
4 +
5 import io.flutter.embedding.android.FlutterFragmentActivity;
6 import io.flutter.embedding.engine.FlutterEngine;
7 import io.flutter.plugins.GeneratedPluginRegistrant;
8
9 +import io.flutter.plugin.common.MethodCall;
10 +import io.flutter.plugin.common.MethodChannel;
11 +
12 +import android.os.AsyncTask;
13 +import android.os.Handler;
14 +import android.os.Looper;
15 +
16 +import java.security.SecureRandom;
17
18 public class MainActivity extends FlutterFragmentActivity {
19 + final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
20
21 @Override
22 public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
23 GeneratedPluginRegistrant.registerWith(flutterEngine);
24 +
25 + MethodChannel utilsChannel =
26 + new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
27 + UTILS_CHANNEL);
28 +
29 + utilsChannel.setMethodCallHandler(this::handle);
30 + }
31 +
32 + private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
33 + Handler handler = new Handler(Looper.getMainLooper());
34 +
35 + try {
36 + if (call.method.equals("sec_random")) {
37 + int count = call.argument("count");
38 + SecureRandom random = new SecureRandom();
39 + byte bytes[] = new byte[count];
40 + random.nextBytes(bytes);
41 + handler.post(() -> result.success(bytes));
42 + } else {
43 + handler.post(() -> result.notImplemented());
44 + }
45 + } catch (Exception e) {
46 + handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null));
47 + }
48 }
49 }
android/app/src/main/kotlin/com/cakewallet/cake_wallet/MainActivity.kt deleted
-13
@@ -1,13 +0,0 @@
1 -package com.cakewallet.cake_wallet
2 -
3 -import androidx.annotation.NonNull;
4 -import io.flutter.embedding.android.FlutterActivity
5 -import io.flutter.embedding.android.FlutterFragmentActivity
6 -import io.flutter.embedding.engine.FlutterEngine
7 -import io.flutter.plugins.GeneratedPluginRegistrant
8 -
9 -class MainActivity: FlutterActivity() {
10 - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine){
11 - GeneratedPluginRegistrant.registerWith(flutterEngine);
12 - }
13 -}
ios/CakeWallet/secRandom.swift new
+12
@@ -0,0 +1,12 @@
1 +import Foundation
2 +
3 +func secRandom(count: Int) -> Data? {
4 + var bytes = [Int8](repeating: 0, count: count)
5 + let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
6 +
7 + if status == errSecSuccess {
8 + return Data(bytes: bytes, count: bytes.count)
9 + }
10 +
11 + return nil
12 +}
ios/Runner.xcodeproj/project.pbxproj
+10 -6
@@ -8,6 +8,7 @@
8
9 /* Begin PBXBuildFile section */
10 0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C44A7192518EF8000B570ED /* decrypt.swift */; };
11 + 0C9D68C9264854B60011B691 /* secRandom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9D68C8264854B60011B691 /* secRandom.swift */; };
12 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
13 20ED0868E1BD7E12278C0CB3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B26E3F56D69167FBB1DC160A /* Pods_Runner.framework */; };
14 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
@@ -21,6 +22,7 @@
22 0C400E0F25B21ABB0025E469 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
23 0C44A7192518EF8000B570ED /* decrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = decrypt.swift; sourceTree = "<group>"; };
24 0C9986A3251A932F00D566FD /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
25 + 0C9D68C8264854B60011B691 /* secRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = secRandom.swift; sourceTree = "<group>"; };
26 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
27 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
28 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 @@
67 isa = PBXGroup;
68 children = (
69 0C44A7192518EF8000B570ED /* decrypt.swift */,
70 + 0C9D68C8264854B60011B691 /* secRandom.swift */,
71 );
72 path = CakeWallet;
73 sourceTree = "<group>";
@@ -274,6 +277,7 @@
277 files = (
278 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
279 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
280 + 0C9D68C9264854B60011B691 /* secRandom.swift in Sources */,
281 0C44A71A2518EF8000B570ED /* decrypt.swift in Sources */,
282 );
283 runOnlyForDeploymentPostprocessing = 0;
@@ -358,7 +362,7 @@
362 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
363 CLANG_ENABLE_MODULES = YES;
364 CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
361 - CURRENT_PROJECT_VERSION = 35;
365 + CURRENT_PROJECT_VERSION = 36;
366 DEVELOPMENT_TEAM = 32J6BB6VUS;
367 ENABLE_BITCODE = NO;
368 FRAMEWORK_SEARCH_PATHS = (
@@ -375,7 +379,7 @@
379 "$(inherited)",
380 "$(PROJECT_DIR)/Flutter",
381 );
378 - MARKETING_VERSION = 4.1.6;
382 + MARKETING_VERSION = 4.1.7;
383 PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
384 PRODUCT_NAME = "$(TARGET_NAME)";
385 SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -501,7 +505,7 @@
505 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
506 CLANG_ENABLE_MODULES = YES;
507 CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
504 - CURRENT_PROJECT_VERSION = 35;
508 + CURRENT_PROJECT_VERSION = 36;
509 DEVELOPMENT_TEAM = 32J6BB6VUS;
510 ENABLE_BITCODE = NO;
511 FRAMEWORK_SEARCH_PATHS = (
@@ -518,7 +522,7 @@
522 "$(inherited)",
523 "$(PROJECT_DIR)/Flutter",
524 );
521 - MARKETING_VERSION = 4.1.6;
525 + MARKETING_VERSION = 4.1.7;
526 PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
527 PRODUCT_NAME = "$(TARGET_NAME)";
528 SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -536,7 +540,7 @@
540 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
541 CLANG_ENABLE_MODULES = YES;
542 CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
539 - CURRENT_PROJECT_VERSION = 35;
543 + CURRENT_PROJECT_VERSION = 36;
544 DEVELOPMENT_TEAM = 32J6BB6VUS;
545 ENABLE_BITCODE = NO;
546 FRAMEWORK_SEARCH_PATHS = (
@@ -553,7 +557,7 @@
557 "$(inherited)",
558 "$(PROJECT_DIR)/Flutter",
559 );
556 - MARKETING_VERSION = 4.1.6;
560 + MARKETING_VERSION = 4.1.7;
561 PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
562 PRODUCT_NAME = "$(TARGET_NAME)";
563 SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
ios/Runner/AppDelegate.swift
+22 -3
@@ -8,9 +8,10 @@ import Flutter
8 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 ) -> Bool {
10 let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
11 - let batteryChannel = FlutterMethodChannel(name: "com.cakewallet.cakewallet/legacy_wallet_migration",
12 - binaryMessenger: controller.binaryMessenger)
13 - batteryChannel.setMethodCallHandler({
11 + let legacyMigrationChannel = FlutterMethodChannel(
12 + name: "com.cakewallet.cakewallet/legacy_wallet_migration",
13 + binaryMessenger: controller.binaryMessenger)
14 + legacyMigrationChannel.setMethodCallHandler({
15 (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
16
17 switch call.method {
@@ -52,6 +53,24 @@ import Flutter
53 }
54 })
55
56 + let utilsChannel = FlutterMethodChannel(
57 + name: "com.cake_wallet/native_utils",
58 + binaryMessenger: controller.binaryMessenger)
59 + utilsChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
60 + switch call.method {
61 + case "sec_random":
62 + guard let args = call.arguments as? Dictionary<String, Any>,
63 + let count = args["count"] as? Int else {
64 + result(nil)
65 + return
66 + }
67 +
68 + result(secRandom(count: count))
69 + default:
70 + result(FlutterMethodNotImplemented)
71 + }
72 + })
73 +
74 GeneratedPluginRegistrant.register(with: self)
75 return super.application(application, didFinishLaunchingWithOptions: launchOptions)
76 }
lib/bitcoin/bitcoin_mnemonic.dart
+5 -16
@@ -4,23 +4,11 @@ import 'dart:typed_data';
4 import 'package:crypto/crypto.dart';
5 import 'package:unorm_dart/unorm_dart.dart' as unorm;
6 import 'package:cryptography/cryptography.dart' as cryptography;
7 +import 'package:cake_wallet/core/sec_random_native.dart';
8
9 const segwit = '100';
10 final wordlist = englishWordlist;
11
11 -Uint8List randomBytes(int length, {bool secure = false}) {
12 - assert(length > 0);
13 -
14 - final random = secure ? Random.secure() : Random();
15 - final ret = Uint8List(length);
16 -
17 - for (var i = 0; i < length; i++) {
18 - ret[i] = random.nextInt(256);
19 - }
20 -
21 - return ret;
22 -}
23 -
12 double logBase(num x, num base) => log(x) / log(base);
13
14 String mnemonicEncode(int i) {
@@ -102,14 +90,15 @@ List<bool> prefixMatches(String source, List<String> prefixes) {
90 return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList();
91 }
92
105 -String generateMnemonic({int strength = 132, String prefix = segwit}) {
93 +Future<String> generateMnemonic(
94 + {int strength = 264, String prefix = segwit}) async {
95 final wordBitlen = logBase(wordlist.length, 2).ceil();
96 final wordCount = strength / wordBitlen;
97 final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil();
98 var result = '';
99
100 do {
112 - final bytes = randomBytes(byteCount);
101 + final bytes = await secRandom(byteCount);
102 maskBytes(bytes, strength);
103 result = encode(bytes);
104 } while (!prefixMatches(result, [prefix]).first);
@@ -134,7 +123,7 @@ bool matchesAnyPrefix(String mnemonic) =>
123 bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
124 try {
125 return matchesAnyPrefix(mnemonic);
137 - } catch(e) {
126 + } catch (e) {
127 return false;
128 }
129 }
lib/bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart
+1 -1
@@ -1,5 +1,5 @@
1 class BitcoinMnemonicIsIncorrectException implements Exception {
2 @override
3 String toString() =>
4 - 'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 words separated by space.';
4 + 'Bitcoin mnemonic has incorrect format. Mnemonic should contain 24 words separated by space.';
5 }
lib/bitcoin/bitcoin_wallet_service.dart
+2 -2
@@ -25,7 +25,7 @@ class BitcoinWalletService extends WalletService<
25 type: WalletType.bitcoin, name: credentials.name);
26 final wallet = BitcoinWalletBase.build(
27 dirPath: dirPath,
28 - mnemonic: generateMnemonic(),
28 + mnemonic: await generateMnemonic(),
29 password: credentials.password,
30 name: credentials.name,
31 walletInfo: credentials.walletInfo);
@@ -47,7 +47,7 @@ class BitcoinWalletService extends WalletService<
47 final walletPath = '$walletDirPath/$name';
48 final walletJSONRaw = await read(path: walletPath, password: password);
49 final walletInfo = walletInfoSource.values.firstWhere(
50 - (info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
50 + (info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
51 orElse: () => null);
52 final wallet = BitcoinWalletBase.fromJSON(
53 password: password,
lib/core/sec_random_native.dart new
+13
@@ -0,0 +1,13 @@
1 +import 'dart:typed_data';
2 +
3 +import 'package:flutter/services.dart';
4 +
5 +const utils = const MethodChannel('com.cake_wallet/native_utils');
6 +
7 +Future<Uint8List> secRandom(int count) async {
8 + try {
9 + return await utils.invokeMethod<Uint8List>('sec_random', {'count': count});
10 + } on PlatformException catch (_) {
11 + return Uint8List.fromList([]);
12 + }
13 +}
lib/monero/monero_wallet_service.dart
+1 -1
@@ -228,7 +228,7 @@ class MoneroWalletService extends WalletService<
228 final name = f.path.split('/').last;
229 final newPath = newWalletDirPath + '/$name';
230 final newFile = File(newPath);
231 - print(file.path);
231 +
232 if (!newFile.existsSync()) {
233 newFile.createSync();
234 }
lib/src/screens/seed/pre_seed_page.dart
+4 -2
@@ -13,7 +13,7 @@ class PreSeedPage extends BasePage {
13 imageDark = Image.asset('assets/images/pre_seed_dark.png'),
14 wordsCount = type == WalletType.monero
15 ? 25
16 - : 12; // FIXME: Stupid fast implementation
16 + : 24; // FIXME: Stupid fast implementation
17
18 final Image imageDark;
19 final Image imageLight;
@@ -49,7 +49,9 @@ class PreSeedPage extends BasePage {
49 Padding(
50 padding: EdgeInsets.only(top: 70, left: 16, right: 16),
51 child: Text(
52 - S.of(context).pre_seed_description(wordsCount.toString()),
52 + S
53 + .of(context)
54 + .pre_seed_description(wordsCount.toString()),
55 textAlign: TextAlign.center,
56 style: TextStyle(
57 fontSize: 14,
pubspec.yaml
+1 -1
@@ -11,7 +11,7 @@ description: Cake Wallet.
11 # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 # Read more about iOS versioning at
13 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 -version: 4.1.6+45
14 +version: 4.1.7+46
15
16 environment:
17 sdk: ">=2.7.0 <3.0.0"
res/values/strings_de.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Beschreibung zur Wiederherstellung der Brieftasche",
171 "restore_new_seed" : "Neuer Seed",
172 "restore_active_seed" : "Aktives Seed",
173 - "restore_bitcoin_description_from_seed" : "Stellen Sie Ihre Brieftasche aus dem 12-Wort-Kombinationscode wieder her",
173 + "restore_bitcoin_description_from_seed" : "Stellen Sie Ihre Brieftasche aus dem 24-Wort-Kombinationscode wieder her",
174 "restore_bitcoin_description_from_keys" : "Stellen Sie Ihre Brieftasche aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her",
175 "restore_bitcoin_title_from_keys" : "Aus WIF wiederherstellen",
176 "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",
res/values/strings_es.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Restaurar billetera",
171 "restore_new_seed" : "Nueva semilla",
172 "restore_active_seed" : "Semilla activa",
173 - "restore_bitcoin_description_from_seed" : "Restaure su billetera a partir del código de combinación de 12 palabras",
173 + "restore_bitcoin_description_from_seed" : "Restaure su billetera a partir del código de combinación de 24 palabras",
174 "restore_bitcoin_description_from_keys" : "Restaure su billetera a partir de una cadena WIF generada a partir de sus claves privadas",
175 "restore_bitcoin_title_from_keys" : "Restaurar desde WIF",
176 "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",
res/values/strings_hi.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "बटुआ विवरण पुनर्स्थापित करें",
171 "restore_new_seed" : "नया बीज",
172 "restore_active_seed" : "सक्रिय बीज",
173 - "restore_bitcoin_description_from_seed" : "12 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें",
173 + "restore_bitcoin_description_from_seed" : "24 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें",
174 "restore_bitcoin_description_from_keys" : "अपने निजी कुंजी से उत्पन्न WIF स्ट्रिंग से अपने वॉलेट को पुनर्स्थापित करें",
175 "restore_bitcoin_title_from_keys" : "WIF से पुनर्स्थापित करें",
176 "restore_from_date_or_blockheight" : "कृपया इस वॉलेट को बनाने से कुछ दिन पहले एक तारीख दर्ज करें। या यदि आप ब्लॉकचेट जानते हैं, तो कृपया इसके बजाय इसे दर्ज करें",
res/values/strings_ja.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "ウォレットの復元",
171 "restore_new_seed" : "新しい種",
172 "restore_active_seed" : "アクティブシード",
173 - "restore_bitcoin_description_from_seed" : "12ワードの組み合わせコードからウォレットを復元する",
173 + "restore_bitcoin_description_from_seed" : "24ワードの組み合わせコードからウォレットを復元する",
174 "restore_bitcoin_description_from_keys" : "秘密鍵から生成されたWIF文字列からウォレットを復元します",
175 "restore_bitcoin_title_from_keys" : "WIFから復元",
176 "restore_from_date_or_blockheight" : "このウォレットを作成する数日前に日付を入力してください。 または、ブロックの高さがわかっている場合は、代わりに入力してください",
res/values/strings_ko.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "월렛 복원 설명",
171 "restore_new_seed" : "새로운 씨앗",
172 "restore_active_seed" : "활성 종자",
173 - "restore_bitcoin_description_from_seed" : "12 단어 조합 코드에서 지갑 복원",
173 + "restore_bitcoin_description_from_seed" : "24 단어 조합 코드에서 지갑 복원",
174 "restore_bitcoin_description_from_keys" : "개인 키에서 생성 된 WIF 문자열에서 지갑 복원",
175 "restore_bitcoin_title_from_keys" : "WIF에서 복원",
176 "restore_from_date_or_blockheight" : "이 지갑을 생성하기 며칠 전에 날짜를 입력하십시오. 또는 블록 높이를 알고있는 경우 대신 입력하십시오.",
res/values/strings_nl.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Portemonnee-herstelbeschrijving",
171 "restore_new_seed" : "Nieuw zaad",
172 "restore_active_seed" : "Actief zaad",
173 - "restore_bitcoin_description_from_seed" : "Herstel uw portemonnee met een combinatiecode van 12 woorden",
173 + "restore_bitcoin_description_from_seed" : "Herstel uw portemonnee met een combinatiecode van 24 woorden",
174 "restore_bitcoin_description_from_keys" : "Herstel uw portemonnee van de gegenereerde WIF-string van uw privésleutels",
175 "restore_bitcoin_title_from_keys" : "Herstel van WIF",
176 "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",
res/values/strings_pl.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Opis przywracania portfela",
171 "restore_new_seed" : "Nowe nasienie",
172 "restore_active_seed" : "Aktywne nasiona",
173 - "restore_bitcoin_description_from_seed" : "Przywróć swój portfel z kodu złożonego z 12 słów",
173 + "restore_bitcoin_description_from_seed" : "Przywróć swój portfel z kodu złożonego z 24 słów",
174 "restore_bitcoin_description_from_keys" : "Przywróć swój portfel z wygenerowanego ciągu WIF z kluczy prywatnych",
175 "restore_bitcoin_title_from_keys" : "Przywróć z WIF",
176 "restore_from_date_or_blockheight" : "Wprowadź datę na kilka dni przed utworzeniem tego portfela. Lub jeśli znasz wysokość bloku, wprowadź go zamiast tego",
res/values/strings_pt.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Restauração da carteira",
171 "restore_new_seed" : "Nova semente",
172 "restore_active_seed" : "Semente ativa",
173 - "restore_bitcoin_description_from_seed" : "Restaure sua carteira a partir de um código de combinação de 12 palavras",
173 + "restore_bitcoin_description_from_seed" : "Restaure sua carteira a partir de um código de combinação de 24 palavras",
174 "restore_bitcoin_description_from_keys" : "Restaure sua carteira a partir da string WIF gerada de suas chaves privadas",
175 "restore_bitcoin_title_from_keys" : "Restaurar de WIF",
176 "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",
res/values/strings_ru.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Описание восстановления кошелька",
171 "restore_new_seed" : "Новая мнемоническая фраза",
172 "restore_active_seed" : "Активная мнемоническая фраза",
173 - "restore_bitcoin_description_from_seed" : "Вы можете восстановить кошелёк используя 12-ти значную мнемоническую фразу",
173 + "restore_bitcoin_description_from_seed" : "Вы можете восстановить кошелёк используя 24-ти значную мнемоническую фразу",
174 "restore_bitcoin_description_from_keys" : "Вы можете восстановить кошелёк с помощью WIF",
175 "restore_bitcoin_title_from_keys" : "Восстановить с помощью WIF",
176 "restore_from_date_or_blockheight" : "Пожалуйста, введите дату за несколько дней до создания этого кошелька. Или, если вы знаете высоту блока, введите ее значение",
res/values/strings_uk.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "Опис відновлюваного гаманця",
171 "restore_new_seed" : "Нова мнемонічна фраза",
172 "restore_active_seed" : "Активна мнемонічна фраза",
173 - "restore_bitcoin_description_from_seed" : "Ви можете відновити гаманець використовуючи 12-ти слівну мнемонічну фразу",
173 + "restore_bitcoin_description_from_seed" : "Ви можете відновити гаманець використовуючи 24-ти слівну мнемонічну фразу",
174 "restore_bitcoin_description_from_keys" : "Ви можете відновити гаманець за допомогою WIF",
175 "restore_bitcoin_title_from_keys" : "Відновити за допомогою WIF",
176 "restore_from_date_or_blockheight" : "Будь ласка, введіть дату за кілька днів до створення цього гаманця. Або, якщо ви знаєте висоту блоку, введіть її значення",
res/values/strings_zh.arb
+1 -1
@@ -170,7 +170,7 @@
170 "restore_wallet_restore_description" : "钱包还原说明",
171 "restore_new_seed" : "新種子",
172 "restore_active_seed" : "活性種子",
173 - "restore_bitcoin_description_from_seed" : "從12個單詞的組合碼恢復您的錢包",
173 + "restore_bitcoin_description_from_seed" : "從24個單詞的組合碼恢復您的錢包",
174 "restore_bitcoin_description_from_keys" : "從私鑰中生成的WIF字符串還原您的錢包",
175 "restore_bitcoin_title_from_keys" : "從WIF還原",
176 "restore_from_date_or_blockheight" : "請在創建此錢包之前幾天輸入一個日期。 或者,如果您知道塊高,請改為輸入",