XOR doesn’t display invalid mnemonic lengths for user selection (#747)
What changed, and why it matters
This commit fixes two user-facing bugs in Krux's 'mnemonic XOR' feature. First, when asking the user to pick a mnemonic length, it now only shows the length that matches the currently loaded wallet (12 or 24 words), preventing the user from accidentally selecting an incompatible length. Second, it now warns the user that the wallet passphrase and descriptor will be discarded before starting the XOR operation, and it corrects the fingerprint shown after the XOR so it no longer incorrectly includes the old passphrase. These are usability and correctness fixes rather than remote-exploitable security holes.
Review the change as a normal bug-fix/UX-hardening commit. No urgent security response is indicated, but downstream users should be aware that prior versions could display a misleading fingerprint during XOR when a passphrase was in use, and allowed selecting an incompatible mnemonic length.
Security signals we found
UI now restricts mnemonic-length selection to the length of the currently loaded key, reducing risk of user error during XOR
Prompt now explicitly warns that passphrase and descriptor will be discarded, improving informed consent
Fingerprint display bug fixed: XOR result fingerprint is now computed from the bare mnemonic instead of inheriting the previous wallet's passphrase
No evidence of memory corruption, remote code execution, or cryptographic weakness introduced
Evidence from the diff
The patch refactors choose_len_mnemonic into a Page method and overrides it in MnemonicXOR so the menu only offers the current wallet’s word count. It removes the old MnemonicXOR.load() menu in favor of the inherited MnemonicLoader.load_key() flow. It updates the XOR prompt text to disclose that passphrase and descriptor are discarded, and changes fingerprint computation to use Key.extract_fingerprint(mnemonic) without a passphrase, fixing a display bug where the XOR result fingerprint was computed with the previous wallet’s passphrase. Translation files and tests are updated accordingly.
Changed components
src/krux/pages/home_pages/mnemonic_xor.pysrc/krux/pages/__init__.pysrc/krux/pages/login.pysrc/krux/pages/mnemonic_loader.pysrc/krux/pages/new_mnemonic/dice_rolls.pysrc/krux/pages/home_pages/bip85.pysrc/krux/pages/home_pages/home.pyi18n translation filestests/pages/home_pages/test_mnemonic_xor.pyInspect captured patch +189 / −201
diff --git a/i18n/i18n.py b/i18n/i18n.py
index dced17b..0e0c1e1 100644
--- a/i18n/i18n.py
+++ b/i18n/i18n.py
@@ -94,8 +94,13 @@ def find_translation_slugs():
continue
with open(join(dirpath, filename), "r", encoding="utf8") as src_file:
contents = src_file.read()
- for match in re.findall(r"[^A-Za-z0-9]t\(\s*\"(.+?)\"\s*\)", contents):
- slugs[match] = True
+ for match in re.findall(
+ r'[^A-Za-z0-9]t\(\s*((?:"[^"]*"\s*)+)\)', contents
+ ):
+ # Extract all string pieces and join them
+ parts = re.findall(r'"([^"]*)"', match)
+ slug = "".join(parts)
+ slugs[slug] = True
return slugs
diff --git a/i18n/translations/de-DE.json b/i18n/translations/de-DE.json
index a02818c..76ddc6c 100644
--- a/i18n/translations/de-DE.json
+++ b/i18n/translations/de-DE.json
@@ -128,6 +128,7 @@
"High fees!": "Hohe Gebühren!",
"ID": "ID",
"ID already exists": "ID existiert bereits",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Wenn Ihr Gerätedisplay nach dieser Änderung nicht funktioniert, wird es nach 5 Sekunden automatisch mit den vorherigen Einstellungen neu gestartet.",
"Index": "Index",
"Inputs (%d):": "Input (%d):",
"Insufficient entropy!": "Unzureichende Entropie!",
@@ -348,7 +349,7 @@
"Words": "Wörter",
"XOR Result": "XOR-Ergebnis",
"XOR With": "XOR mit",
- "XOR current mnemonic with another one ?": "XOR-Strommnemotechnik mit einer anderen?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR-Strommnemotechnik mit einer anderen? (Passphrase und Deskriptor werden verworfen)",
"Yes": "Ja",
"Zoomed mode": "Zoommodus",
"binary:": "binär:",
@@ -372,4 +373,4 @@
"to utf8": "zu utf8",
"unknown": "unbekannt",
"was NOT FOUND in the first %d addresses": "wurde in den ersten %d Adressen nicht gefunden"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/es-MX.json b/i18n/translations/es-MX.json
index 18b6ec2..5941558 100644
--- a/i18n/translations/es-MX.json
+++ b/i18n/translations/es-MX.json
@@ -128,6 +128,7 @@
"High fees!": "¡Tarifas altas!",
"ID": "Identificador",
"ID already exists": "ID ya existe",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Si la pantalla de su dispositivo no funciona después de este cambio, se reiniciará automáticamente con la configuración anterior después de 5 segundos.",
"Index": "Índice",
"Inputs (%d):": "Entradas (%d):",
"Insufficient entropy!": "¡Entropía Insuficiente!",
@@ -348,7 +349,7 @@
"Words": "Palabras",
"XOR Result": "Resultado XOR",
"XOR With": "XOR Con",
- "XOR current mnemonic with another one ?": "¿XOR mnemotécnico actual con otro ?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "¿XOR mnemónico actual con otro? (se descartarán la passphrase y el descriptor)",
"Yes": "Sí",
"Zoomed mode": "Modo ampliado",
"binary:": "binario:",
@@ -372,4 +373,4 @@
"to utf8": "a utf8",
"unknown": "desconocido",
"was NOT FOUND in the first %d addresses": "NO FUE ENCONTRADO en las primeras %d direcciones"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/fr-FR.json b/i18n/translations/fr-FR.json
index f1c6976..06ae9bc 100644
--- a/i18n/translations/fr-FR.json
+++ b/i18n/translations/fr-FR.json
@@ -128,6 +128,7 @@
"High fees!": "Frais élevés !",
"ID": "ID",
"ID already exists": "Id existe déjà",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Si l'affichage de votre appareil ne fonctionne pas après ce changement, il redémarrera automatiquement avec les paramètres précédents après 5 secondes.",
"Index": "Index",
"Inputs (%d):": "Entrées (%d) :",
"Insufficient entropy!": "Entropie insuffisante !",
@@ -348,7 +349,7 @@
"Words": "Mots",
"XOR Result": "Résultat XOR",
"XOR With": "XOR avec",
- "XOR current mnemonic with another one ?": "XOR mnémonique actuel avec un autre ?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR mnémonique actuel avec un autre ? (la phrase secrète et le descripteur seront supprimés)",
"Yes": "Oui",
"Zoomed mode": "Mode zoomé",
"binary:": "binaire :",
@@ -372,4 +373,4 @@
"to utf8": "vers utf8",
"unknown": "inconnu",
"was NOT FOUND in the first %d addresses": "INTROUVABLE dans les %d premières adresses"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/ja-JP.json b/i18n/translations/ja-JP.json
index 4832282..4c2d7b4 100644
--- a/i18n/translations/ja-JP.json
+++ b/i18n/translations/ja-JP.json
@@ -128,6 +128,7 @@
"High fees!": "高い手数料!",
"ID": "ID",
"ID already exists": "IDはすでに存在します",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "この変更後にデバイスのディスプレイが動作しない場合、5秒後に以前の設定で自動的に再起動します.",
"Index": "インデックス",
"Inputs (%d):": "インプット(%d):",
"Insufficient entropy!": "不十分なエントロピー!",
@@ -348,7 +349,7 @@
"Words": "単語",
"XOR Result": "XOR結果",
"XOR With": "XOR With",
- "XOR current mnemonic with another one ?": "XOR現在のニーモニックと別のニーモニック?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR現在のニーモニックと別のニーモニック? (パスフレーズと記述子は破棄されます)",
"Yes": "はい",
"Zoomed mode": "ズームモード",
"binary:": "バイナリ:",
@@ -372,4 +373,4 @@
"to utf8": "utf 8へ",
"unknown": "不明",
"was NOT FOUND in the first %d addresses": "最初の%dアドレスに見つかりませんでした"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/ko-KR.json b/i18n/translations/ko-KR.json
index 0064a73..0cf4250 100644
--- a/i18n/translations/ko-KR.json
+++ b/i18n/translations/ko-KR.json
@@ -128,6 +128,7 @@
"High fees!": "수수료가 높습니다!",
"ID": "ID",
"ID already exists": "아이디가 이미 존재합니다",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "이 변경 후에도 장치 디스플레이가 작동하지 않으면 5초 후에 이전 설정으로 자동으로 재부팅됩니다.",
"Index": "인덱스",
"Inputs (%d):": "Input (%d):",
"Insufficient entropy!": "엔트로피가 충분하지 않습니다!",
@@ -348,7 +349,7 @@
"Words": "시드문구",
"XOR Result": "XOR 결과",
"XOR With": "XOR With",
- "XOR current mnemonic with another one ?": "다른 XOR 전류 니모닉과 함께?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "다른 XOR 전류 니모닉? (패스프레이즈와 디스크립터가 폐기됩니다)",
"Yes": "예",
"Zoomed mode": "확대 모드",
"binary:": "바이너리:",
@@ -372,4 +373,4 @@
"to utf8": "utf8로",
"unknown": "알 수 없음",
"was NOT FOUND in the first %d addresses": "첫 번째 %d개의 주소에서 찾을 수 없습니다"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/nl-NL.json b/i18n/translations/nl-NL.json
index a6307bf..0b997df 100644
--- a/i18n/translations/nl-NL.json
+++ b/i18n/translations/nl-NL.json
@@ -128,6 +128,7 @@
"High fees!": "Hoge kosten!",
"ID": "ID",
"ID already exists": "ID bestaat al",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Als het scherm van uw apparaat na deze wijziging niet werkt, wordt het na 5 seconden automatisch opnieuw opgestart met de vorige instellingen.",
"Index": "Index",
"Inputs (%d):": "Invoer (%d):",
"Insufficient entropy!": "Onvoldoende Entropie!",
@@ -348,7 +349,7 @@
"Words": "Woorden",
"XOR Result": "XOR-resultaat",
"XOR With": "XOR met",
- "XOR current mnemonic with another one ?": "XOR huidig geheugensteuntje met een ander ?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR huidig geheugensteuntje met een ander? (passphrase en descriptor worden weggegooid)",
"Yes": "Yes",
"Zoomed mode": "Ingezoomde modus",
"binary:": "binair:",
@@ -372,4 +373,4 @@
"to utf8": "naar utf8",
"unknown": "onbekend",
"was NOT FOUND in the first %d addresses": "werd NIET GEVONDEN in de eerste %d adressen"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/pt-BR.json b/i18n/translations/pt-BR.json
index 7fcf3e6..6ad0dcc 100644
--- a/i18n/translations/pt-BR.json
+++ b/i18n/translations/pt-BR.json
@@ -128,6 +128,7 @@
"High fees!": "Taxas altas!",
"ID": "ID",
"ID already exists": "ID já existe",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Se a tela do seu dispositivo não funcionar após essa alteração, ele será reiniciado automaticamente com as configurações anteriores após 5 segundos.",
"Index": "Índice",
"Inputs (%d):": "Entradas (%d):",
"Insufficient entropy!": "Entropia insuficiente!",
@@ -348,7 +349,7 @@
"Words": "Palavras",
"XOR Result": "Resultado XOR",
"XOR With": "XOR com",
- "XOR current mnemonic with another one ?": "XOR atual mnemônico com outro ?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR atual mnemônico com outro? (senha e descritor serão descartados)",
"Yes": "Sim",
"Zoomed mode": "Modo ampliado",
"binary:": "binário:",
@@ -372,4 +373,4 @@
"to utf8": "para utf8",
"unknown": "desconhecida",
"was NOT FOUND in the first %d addresses": "NÃO FOI ENCONTRADO nos primeiros %d endereços"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/ru-RU.json b/i18n/translations/ru-RU.json
index e031065..6acb2b1 100644
--- a/i18n/translations/ru-RU.json
+++ b/i18n/translations/ru-RU.json
@@ -128,6 +128,7 @@
"High fees!": "Высокие комиссии!",
"ID": "Идентификатор",
"ID already exists": "ID уже существует",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Если после этого изменения дисплей устройства не работает, он автоматически перезагрузится с предыдущими настройками через 5 секунд.",
"Index": "Индекс",
"Inputs (%d):": "Входы (%d):",
"Insufficient entropy!": "Недостаточная Энтропия!",
@@ -348,7 +349,7 @@
"Words": "Слова",
"XOR Result": "Результат XOR",
"XOR With": "XOR с",
- "XOR current mnemonic with another one ?": "XOR current mnemonic с другой ?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR current mnemonic with another one? (парольная фраза и дескриптор будут отброшены)",
"Yes": "Да",
"Zoomed mode": "Режим масштабирования",
"binary:": "двоичный:",
@@ -372,4 +373,4 @@
"to utf8": "to utf8",
"unknown": "неизвестный",
"was NOT FOUND in the first %d addresses": "нЕ НАЙДЕНО в первых %d адресах"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/tr-TR.json b/i18n/translations/tr-TR.json
index 199153c..588ec91 100644
--- a/i18n/translations/tr-TR.json
+++ b/i18n/translations/tr-TR.json
@@ -128,6 +128,7 @@
"High fees!": "Yüksek ücret!",
"ID": "ID",
"ID already exists": "ID zaten var",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Bu değişiklikten sonra cihazınızın ekranı çalışmazsa, 5 saniye sonra önceki ayarlarla otomatik olarak yeniden başlatılır.",
"Index": "Dizin",
"Inputs (%d):": "Girişler (%d):",
"Insufficient entropy!": "Yetersiz entropi!",
@@ -348,7 +349,7 @@
"Words": "Kelimeler",
"XOR Result": "XOR Sonucu",
"XOR With": "XOR ile",
- "XOR current mnemonic with another one ?": "XOR akım anımsatıcı başka bir tane ile?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR başka biriyle geçerli anımsatıcı? (parola ve tanımlayıcı atılacak)",
"Yes": "Evet",
"Zoomed mode": "Zoom Mod",
"binary:": "ikili:",
@@ -372,4 +373,4 @@
"to utf8": "utf8 'e",
"unknown": "bilinmiyor",
"was NOT FOUND in the first %d addresses": "ilk %d adreste BULUNAMADI"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/vi-VN.json b/i18n/translations/vi-VN.json
index d46f6c3..7a86932 100644
--- a/i18n/translations/vi-VN.json
+++ b/i18n/translations/vi-VN.json
@@ -128,6 +128,7 @@
"High fees!": "Phí cao!",
"ID": "ID",
"ID already exists": "Id đã tồn tại",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "Nếu màn hình thiết bị của bạn không hoạt động sau khi thay đổi này, màn hình sẽ tự động khởi động lại với các cài đặt trước đó sau 5 giây.",
"Index": "Chỉ mục",
"Inputs (%d):": "Đầu vào (%d):",
"Insufficient entropy!": "Entropy không đủ!",
@@ -348,7 +349,7 @@
"Words": "Từ ngữ",
"XOR Result": "Kết quả XOR",
"XOR With": "XOR với",
- "XOR current mnemonic with another one ?": "Từ gợi nhớ hiện tại của XOR với từ gợi nhớ khác ?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "Ghi nhớ hiện tại của XOR với một cụm từ khác? (cụm mật khẩu và mô tả sẽ bị loại bỏ)",
"Yes": "Đúng",
"Zoomed mode": "Chế độ thu phóng",
"binary:": "nhị phân:",
@@ -372,4 +373,4 @@
"to utf8": "đến utf8",
"unknown": "không rõ",
"was NOT FOUND in the first %d addresses": "kHÔNG TÌM THẤY trong %d địa chỉ đầu tiên"
-}
+}
\ No newline at end of file
diff --git a/i18n/translations/zh-CN.json b/i18n/translations/zh-CN.json
index a984135..212e24e 100644
--- a/i18n/translations/zh-CN.json
+++ b/i18n/translations/zh-CN.json
@@ -128,6 +128,7 @@
"High fees!": "高费用!",
"ID": "ID",
"ID already exists": "ID 已存在",
+ "If your device display does not work after this change, it will automatically reboot with previous settings after 5 seconds.": "如果您的设备显示屏在此更改后无法正常工作,它将在5秒后使用以前的设置自动重新启动.",
"Index": "索引",
"Inputs (%d):": "输入 (%d):",
"Insufficient entropy!": "熵不足!",
@@ -348,7 +349,7 @@
"Words": "单词",
"XOR Result": "XOR结果",
"XOR With": "XOR With",
- "XOR current mnemonic with another one ?": "XOR当前助记符与其他助记符?",
+ "XOR current mnemonic with another one? (passphrase and descriptor will be discarded)": "XOR当前助记符与其他助记符? (密码短语和描述符将被丢弃)",
"Yes": "是",
"Zoomed mode": "放大模式",
"binary:": "二进制:",
@@ -372,4 +373,4 @@
"to utf8": "to_utf8()",
"unknown": "未知",
"was NOT FOUND in the first %d addresses": "在前 %d 个地址中未找到"
-}
+}
\ No newline at end of file
diff --git a/src/krux/pages/__init__.py b/src/krux/pages/__init__.py
index cd42214..ac88f9b 100644
--- a/src/krux/pages/__init__.py
+++ b/src/krux/pages/__init__.py
@@ -575,6 +575,19 @@ class Page:
theme.frame_color,
)
+ def choose_len_mnemonic(self, extra_option=""):
+ """Reusable '12 or 24 words?" menu choice"""
+ items = [
+ (t("12 words"), lambda: 12),
+ (t("24 words"), lambda: 24),
+ ]
+ if extra_option:
+ items.append((extra_option, lambda: EXTRA_MNEMONIC_LENGTH_FLAG))
+ submenu = Menu(self.ctx, items, back_status=lambda: None)
+ _, num_words = submenu.run_loop()
+ self.ctx.display.clear()
+ return num_words
+
class ListView:
"""Acts as a fixed-size, sliding window over an underlying list"""
@@ -1011,17 +1024,3 @@ class Menu:
text, offset_y + FONT_HEIGHT * j, fg_color
)
offset_y += delta_y
-
-
-def choose_len_mnemonic(ctx, extra_option=""):
- """Reusable '12 or 24 words?" menu choice"""
- items = [
- (t("12 words"), lambda: 12),
- (t("24 words"), lambda: 24),
- ]
- if extra_option:
- items.append((extra_option, lambda: EXTRA_MNEMONIC_LENGTH_FLAG))
- submenu = Menu(ctx, items, back_status=lambda: None)
- _, num_words = submenu.run_loop()
- ctx.display.clear()
- return num_words
diff --git a/src/krux/pages/home_pages/bip85.py b/src/krux/pages/home_pages/bip85.py
index d0db659..c184024 100644
--- a/src/krux/pages/home_pages/bip85.py
+++ b/src/krux/pages/home_pages/bip85.py
@@ -30,7 +30,6 @@ from .. import (
Menu,
Page,
MENU_CONTINUE,
- choose_len_mnemonic,
)
BIP_PWD_APP_INDEX = 707764
@@ -44,7 +43,7 @@ class Bip85(Page):
def _derive_mnemonic(self):
"""Derive a BIP85 mnemonic"""
- num_words = choose_len_mnemonic(self.ctx)
+ num_words = self.choose_len_mnemonic()
if not num_words:
return MENU_CONTINUE
diff --git a/src/krux/pages/home_pages/home.py b/src/krux/pages/home_pages/home.py
index bc694c8..efacd43 100644
--- a/src/krux/pages/home_pages/home.py
+++ b/src/krux/pages/home_pages/home.py
@@ -166,7 +166,10 @@ class Home(Page):
def mnemonic_xor(self):
"""Handler for the 'Mnemonic XOR' menu item"""
if not self.prompt(
- t("XOR current mnemonic with another one ?"),
+ t(
+ "XOR current mnemonic with another one? "
+ "(passphrase and descriptor will be discarded)"
+ ),
self.ctx.display.height() // 2,
):
return MENU_CONTINUE
@@ -174,7 +177,7 @@ class Home(Page):
from .mnemonic_xor import MnemonicXOR
mnemonic_xor = MnemonicXOR(self.ctx)
- mnemonic_xor.load()
+ mnemonic_xor.load_key()
return MENU_CONTINUE
diff --git a/src/krux/pages/home_pages/mnemonic_xor.py b/src/krux/pages/home_pages/mnemonic_xor.py
index 525056e..454f99a 100644
--- a/src/krux/pages/home_pages/mnemonic_xor.py
+++ b/src/krux/pages/home_pages/mnemonic_xor.py
@@ -109,71 +109,43 @@ class MnemonicXOR(MnemonicLoader):
color=theme.highlight_color,
)
- def load(self):
- """Menu for XOR the current mnemonic with a share"""
- menu = Menu(
- self.ctx,
- [
- (t("Via Camera"), self.load_key_from_camera),
- (t("Via Manual Input"), self.load_key_from_manual_input),
- (t("From Storage"), self.load_mnemonic_from_storage),
- ],
- )
-
- menu.run_loop()
- return MENU_EXIT
-
def _load_key_from_words(self, words, charset=LETTERS, new=False):
"""
Similar method from krux.pages.login.Login without loading a key,
instead, it add the bytes from a mnemonic's entropy to the list of entropies
"""
- # Memorize the current fingerprint to use it later
- current_fingerprint = self.ctx.wallet.key.fingerprint_hex_str(True)
-
- # Show mnemonic which will be used for XOR with current one
mnemonic_to_xor = " ".join(words)
- key_to_xor = Key(
- mnemonic_to_xor,
- self.ctx.wallet.key.policy_type,
- self.ctx.wallet.key.network,
- "",
- self.ctx.wallet.key.account_index,
- self.ctx.wallet.key.script_type,
- )
- # Memorize the fingerprint to XOR to use later
- fingerprint_to_xor = key_to_xor.fingerprint_hex_str(True)
+ fingerprint_to_xor = Key.extract_fingerprint(mnemonic_to_xor)
# Show the mnemonic to XOR with
self._display_key_info(
mnemonic_to_xor,
- key_to_xor.fingerprint_hex_str(True),
+ fingerprint_to_xor,
t("XOR With") + ":",
)
if not self.prompt(t("Proceed?"), BOTTOM_PROMPT_LINE):
return MENU_CONTINUE
- xored_mnemonic = self.xor_with_current_mnemonic(key_to_xor.mnemonic)
- xored_key = Key(
- xored_mnemonic,
- self.ctx.wallet.key.policy_type,
- self.ctx.wallet.key.network,
- "",
- self.ctx.wallet.key.account_index,
- self.ctx.wallet.key.script_type,
- )
+ self.ctx.display.clear()
+
+ xored_mnemonic = self.xor_with_current_mnemonic(mnemonic_to_xor)
+ xored_fingerprint = Key.extract_fingerprint(xored_mnemonic)
# Display XOR operation and resulting fingerprint:
- offset_y = self.ctx.display.height() // 2
- offset_y -= FONT_HEIGHT * 3
- self.ctx.display.clear()
- for element in [current_fingerprint, "XOR", fingerprint_to_xor, "="]:
- self.ctx.display.draw_hcentered_text(element, offset_y, theme.fg_color)
- offset_y += FONT_HEIGHT
+ offset_y = (self.ctx.display.height() // 2) - FONT_HEIGHT * 3
+ lines = [
+ Key.extract_fingerprint(self.ctx.wallet.key.mnemonic),
+ "XOR",
+ fingerprint_to_xor,
+ "=",
+ ]
+ self.ctx.display.draw_hcentered_text(lines, offset_y, theme.fg_color)
self.ctx.display.draw_hcentered_text(
- xored_key.fingerprint_hex_str(True), offset_y, theme.highlight_color
+ xored_fingerprint,
+ offset_y + FONT_HEIGHT * len(lines),
+ theme.highlight_color,
)
if not self.prompt(t("Proceed?"), BOTTOM_PROMPT_LINE):
@@ -185,15 +157,35 @@ class MnemonicXOR(MnemonicLoader):
# Show the XOR result
self._display_key_info(
xored_mnemonic,
- xored_key.fingerprint_hex_str(True),
+ xored_fingerprint,
t("XOR Result") + ":",
)
if self.prompt(t("Load?"), BOTTOM_PROMPT_LINE):
+ xored_key = Key(
+ xored_mnemonic,
+ self.ctx.wallet.key.policy_type,
+ self.ctx.wallet.key.network,
+ "",
+ self.ctx.wallet.key.account_index,
+ self.ctx.wallet.key.script_type,
+ )
self.ctx.wallet = Wallet(xored_key)
self.flash_text(
- t("%s: loaded!") % xored_key.fingerprint_hex_str(True),
+ t("%s: loaded!") % xored_fingerprint,
highlight_prefix=":",
)
return MENU_EXIT
+
+ def choose_len_mnemonic(self, extra_option=""):
+ """XOR '12 or 24 words?" menu choice"""
+ items = []
+ if len(self.ctx.wallet.key.mnemonic.split(" ")) == 12:
+ items.append((t("12 words"), lambda: 12))
+ else:
+ items.append((t("24 words"), lambda: 24))
+ submenu = Menu(self.ctx, items, back_status=lambda: None)
+ _, num_words = submenu.run_loop()
+ self.ctx.display.clear()
+ return num_words
diff --git a/src/krux/pages/login.py b/src/krux/pages/login.py
index 6813b9b..82e32cf 100644
--- a/src/krux/pages/login.py
+++ b/src/krux/pages/login.py
@@ -29,7 +29,6 @@ from . import (
MENU_EXIT,
LETTERS,
EXTRA_MNEMONIC_LENGTH_FLAG,
- choose_len_mnemonic,
)
from .mnemonic_loader import MnemonicLoader
from ..display import DEFAULT_PADDING, FONT_HEIGHT, BOTTOM_PROMPT_LINE
@@ -123,7 +122,7 @@ class Login(MnemonicLoader):
def new_key_from_snapshot(self):
"""Use camera's entropy to create a new mnemonic"""
extra_option = t("Double mnemonic")
- len_mnemonic = choose_len_mnemonic(self.ctx, extra_option)
+ len_mnemonic = self.choose_len_mnemonic(extra_option)
if not len_mnemonic:
return MENU_CONTINUE
diff --git a/src/krux/pages/mnemonic_loader.py b/src/krux/pages/mnemonic_loader.py
index e005be3..b2bd0e3 100644
--- a/src/krux/pages/mnemonic_loader.py
+++ b/src/krux/pages/mnemonic_loader.py
@@ -29,7 +29,6 @@ from . import (
MENU_CONTINUE,
ESC_KEY,
LETTERS,
- choose_len_mnemonic,
)
from ..display import BOTTOM_PROMPT_LINE
from ..qr import FORMAT_UR
@@ -119,7 +118,7 @@ class MnemonicLoader(Page):
from .mnemonic_editor import MnemonicEditor
if new:
- len_mnemonic = choose_len_mnemonic(self.ctx)
+ len_mnemonic = self.choose_len_mnemonic()
if not len_mnemonic:
return MENU_CONTINUE
title = t("Enter %d BIP39 words.") % len_mnemonic
@@ -269,7 +268,7 @@ class MnemonicLoader(Page):
"""Menu handler to manually load key from Tinyseed sheet metal storage method"""
from .tiny_seed import TinySeed
- len_mnemonic = choose_len_mnemonic(self.ctx)
+ len_mnemonic = self.choose_len_mnemonic()
if not len_mnemonic:
return MENU_CONTINUE
@@ -284,7 +283,7 @@ class MnemonicLoader(Page):
"""Menu handler to scan key from Tinyseed sheet metal storage method"""
from .tiny_seed import TinyScanner
- len_mnemonic = choose_len_mnemonic(self.ctx)
+ len_mnemonic = self.choose_len_mnemonic()
if not len_mnemonic:
return MENU_CONTINUE
diff --git a/src/krux/pages/new_mnemonic/dice_rolls.py b/src/krux/pages/new_mnemonic/dice_rolls.py
index 95f1326..01ea1aa 100644
--- a/src/krux/pages/new_mnemonic/dice_rolls.py
+++ b/src/krux/pages/new_mnemonic/dice_rolls.py
@@ -25,7 +25,6 @@ from .. import (
Menu,
MENU_EXIT,
ESC_KEY,
- choose_len_mnemonic,
)
from ...themes import theme
from ...krux_settings import t
@@ -229,7 +228,7 @@ class DiceEntropy(Page):
"""Create a new key from dice rolls"""
from ...settings import ELLIPSIS
- len_mnemonic = choose_len_mnemonic(self.ctx)
+ len_mnemonic = self.choose_len_mnemonic()
if not len_mnemonic:
return None
diff --git a/src/krux/translations/__init__.py b/src/krux/translations/__init__.py
index c382ae9..e0900cc 100644
--- a/src/krux/translations/__init__.py
+++ b/src/krux/translations/__init__.py
@@ -50,7 +50,6 @@ ref_array = [
2995482424,
2415648848,
1043817877,
- 1610434839,
3439746594,
4121028614,
3270727197,
@@ -80,7 +79,6 @@ ref_array = [
3119547911,
1187826970,
4011811253,
- 1860915234,
422237057,
1464900930,
3625040530,
@@ -88,7 +86,6 @@ ref_array = [
167798282,
678449760,
1347214433,
- 1590681747,
3513215254,
1741764813,
3585411775,
@@ -103,7 +100,6 @@ ref_array = [
4102535566,
3200465747,
2940689088,
- 3164577772,
1712856005,
4150351825,
3278654271,
@@ -166,6 +162,7 @@ ref_array = [
3876651191,
299066170,
2880010062,
+ 3327483300,
1102202885,
3242179508,
649035497,
@@ -176,8 +173,6 @@ ref_array = [
237577215,
4122897393,
640219121,
- 173596861,
- 149326735,
3218124392,
3000888649,
3264569915,
@@ -211,8 +206,8 @@ ref_array = [
2938615129,
3928301843,
1948316555,
+ 1584070924,
1443208255,
- 3782283369,
1237332019,
4265479636,
2939797024,
@@ -386,8 +381,10 @@ ref_array = [
797660533,
3742424146,
2965123464,
+ 903400125,
+ 3368232542,
+ 3520459693,
1303016265,
- 55888997,
619317523,
1688347225,
3673250051,
diff --git a/src/krux/translations/de.py b/src/krux/translations/de.py
index b6a393d..8802adf 100644
--- a/src/krux/translations/de.py
+++ b/src/krux/translations/de.py
@@ -38,7 +38,6 @@ translation_array = [
"Konto",
"Konto #0 würde angenommen",
"Kontoindex",
- "Einen Anteil hinzufügen",
"Wallet-Passphrase hinzufügen oder ändern?",
"Zusätzliche Entropie von der Kamera erforderlich für %s",
"Adresse",
@@ -68,7 +67,6 @@ translation_array = [
"Überprüfen, ob diese Adresse zu dieser Wallet gehört?",
"Überprüfte %d Adresse ohne Übereinstimmungen.",
"SD-Karte wird gesucht…",
- "Anteile bereinigen",
"Bestätigen Sie den Tamper Check Code",
"Datum konvertieren",
"Änderungsadresse konnte nicht ermittelt werden.",
@@ -76,7 +74,6 @@ translation_array = [
"QR-Code aus Text erstellen?",
"Erstellt:",
"Aktueller Tamper Check Code",
- "Die aktuelle Mnemonic und die Passphrase werden nicht beibehalten.",
"Benutzerdefinierter Link QR-Code",
"Custom Text",
"Anpassen",
@@ -91,7 +88,6 @@ translation_array = [
"Tiefe pro Durchgang",
"Derivation-Pfad",
"BIP85-Entropie ableiten?",
- "Anteile ableiten",
"Deskriptor-Adressen",
"Gerätetests",
"Bildschirm",
@@ -154,6 +150,7 @@ translation_array = [
"Hohe Gebühren!",
"ID",
"ID existiert bereits",
+ "Wenn Ihr Gerätedisplay nach dieser Änderung nicht funktioniert, wird es nach 5 Sekunden automatisch mit den vorherigen Einstellungen neu gestartet.",
"Index",
"Input (%d):",
"Unzureichende Entropie!",
@@ -164,8 +161,6 @@ translation_array = [
"Ungültige Wallet:",
"Umkehren",
"Invertierte Farben",
- "Es werden alle geladenen Anteile gelöscht",
- "Es werden der aktuelle Schlüssel, die Passphrase und der Deskriptor gelöscht.",
"KEF-verschlüsselt",
"Schlüssel",
"Schlüssel wurde nicht zur Verfügung gestellt",
@@ -199,8 +194,8 @@ translation_array = [
"X-Koordinaten spiegeln",
"Fehlende Signaturdatei",
"Mnemonic",
+ "Mnemonisches XOR",
"Mnemotechnik und Passphrase werden beibehalten.",
- "Die Mnemonics werden mit der aktuellen Mnemonic (SeedXOR) XOR-verknüpft.",
"Geändert:",
"Native Segwit - 84 würde angenommen",
"Netzwerk",
@@ -374,8 +369,10 @@ translation_array = [
"Wort %d",
"Wortnummern",
"Wörter",
+ "XOR-Ergebnis",
+ "XOR mit",
+ "XOR-Strommnemotechnik mit einer anderen? (Passphrase und Deskriptor werden verworfen)",
"Ja",
- "Sie können bis zu %d Anteile hinzufügen",
"Zoommodus",
"binär:",
"failed:",
diff --git a/src/krux/translations/es.py b/src/krux/translations/es.py
index 9dc5134..835afe8 100644
--- a/src/krux/translations/es.py
+++ b/src/krux/translations/es.py
@@ -38,7 +38,6 @@ translation_array = [
"Cuenta",
"Se supondría que la cuenta #0",
"Índice de la cuenta",
- "Agregar una participación",
"¿Añadir o cambiar passphrase de la cartera?",
"Se requiere entropía adicional de la cámara para %s",
"Dirección",
@@ -68,7 +67,6 @@ translation_array = [
"¿Verificar que la dirección pertenece a esta cartera?",
"Comprobado %d direcciones sin coincidencias.",
"Buscando tarjeta SD…",
- "Limpiar participaciones",
"Confirmar el código de verificación",
"Convertir dato",
"No se pudo determinar la dirección de cambio.",
@@ -76,7 +74,6 @@ translation_array = [
"¿Crear código QR a partir de texto?",
"Creado:",
"Código de verificación actual",
- "La mnemotécnica actual y la frase de contraseña no se conservarán.",
"Código QR personalizado",
"Texto Personalizado",
"Personalizar",
@@ -91,7 +88,6 @@ translation_array = [
"Profundidad por Pasada",
"Ruta de derivación",
"¿Derivar entropía BIP85?",
- "Derivar participaciones",
"Direcciones del descriptor",
"Pruebas del dispositivo",
"Pantalla",
@@ -154,6 +150,7 @@ translation_array = [
"¡Tarifas altas!",
"Identificador",
"ID ya existe",
+ "Si la pantalla de su dispositivo no funciona después de este cambio, se reiniciará automáticamente con la configuración anterior después de 5 segundos.",
"Índice",
"Entradas (%d):",
"¡Entropía Insuficiente!",
@@ -164,8 +161,6 @@ translation_array = [
"Cartera inválida:",
"Invertir",
"Colores Invertidos",
- "Se limpiarán todas las participaciones cargadas",
- "Se eliminarán la clave actual, la frase de contraseña y el descriptor.",
"Kef encriptado",
"Clave",
"No se proporcionó la clave",
@@ -199,8 +194,8 @@ translation_array = [
"Espejo de coordenadas X",
"Falta archivo de firma",
"Mnemónico",
+ "XOR mnemónico",
"Mnemónico y passphrase se mantendrán.",
- "Las mnemotécnicas se XORarán con la mnemotécnica actual (SeedXOR).",
"Modificado:",
"Segwit nativo - 84 se supondría",
"Red",
@@ -374,8 +369,10 @@ translation_array = [
"Palabra %d",
"Números de Palabra",
"Palabras",
+ "Resultado XOR",
+ "XOR Con",
+ "¿XOR mnemónico actual con otro? (se descartarán la passphrase y el descriptor)",
"Sí",
- "Puedes agregar hasta %d participaciones",
"Modo ampliado",
"binario:",
"failed:",
diff --git a/src/krux/translations/fr.py b/src/krux/translations/fr.py
index cb96b3d..710282a 100644
--- a/src/krux/translations/fr.py
+++ b/src/krux/translations/fr.py
@@ -38,7 +38,6 @@ translation_array = [
"Compte",
"Le compte n °0 serait supposé",
"Index du compte",
- "Ajouter une part",
"Ajoutez ou modifiez la phrase secrète\u2009?",
"Entropie supplémentaire de la caméra requise pour %s",
"Adresse",
@@ -68,7 +67,6 @@ translation_array = [
"Vérifiez que l'adresse appartient à ce portefeuille\u2009?",
"%d adresses vérifiées sans correspondance.",
"Recherche de carte SD…",
- "Nettoyer les parts",
"Confirmer le code de non compromis",
"Convertir le datum",
"Impossible de déterminer l'adresse de monnaie.",
@@ -76,7 +74,6 @@ translation_array = [
"Créer un code QR à partir de texte\u2009?",
"Créé\u2009:",
"Code de non compromis actuel",
- "La mnémonique et la phrase secrète actuelles ne seront pas conservées.",
"Code QR personnalisé",
"Texte personnalisé",
"Personnaliser",
@@ -91,7 +88,6 @@ translation_array = [
"Profondeur par passage",
"Chemin de dérivation",
"Dériver l'entropie BIP85\u2009?",
- "Dériver des parts",
"Adresses du descripteur",
"Tests de l'appareil",
"Affichage",
@@ -154,6 +150,7 @@ translation_array = [
"Frais élevés\u2009!",
"ID",
"Id existe déjà",
+ "Si l'affichage de votre appareil ne fonctionne pas après ce changement, il redémarrera automatiquement avec les paramètres précédents après 5 secondes.",
"Index",
"Entrées (%d)\u2009:",
"Entropie insuffisante\u2009!",
@@ -164,8 +161,6 @@ translation_array = [
"Portefeuille invalide\u2009:",
"Inverser",
"Couleurs inversées",
- "Toutes les parts chargées seront supprimées",
- "La clé actuelle, la phrase secrète et le descripteur seront supprimés.",
"KEF chiffré",
"Clé",
"La clé n'a pas été fournie",
@@ -199,8 +194,8 @@ translation_array = [
"Refléter coordonnées X",
"Fichier de signature manquant",
"Mnémonique",
+ "Mnémonique XOR",
"Mnémonique et phrase secrète seront conservés.",
- "Les mnémoniques seront combinées par XOR avec la mnémonique actuelle (SeedXOR).",
"Modifié\u2009:",
"Native Segwit - 84 serait supposé",
"Réseau",
@@ -374,8 +369,10 @@ translation_array = [
"Mot %d",
"Numéros de mots",
"Mots",
+ "Résultat XOR",
+ "XOR avec",
+ "XOR mnémonique actuel avec un autre\u2009? (la phrase secrète et le descripteur seront supprimés)",
"Oui",
- "Vous pouvez ajouter jusqu’à %d parts",
"Mode zoomé",
"binaire\u2009:",
"echoué",
diff --git a/src/krux/translations/ja.py b/src/krux/translations/ja.py
index 6316f40..85bd471 100644
--- a/src/krux/translations/ja.py
+++ b/src/krux/translations/ja.py
@@ -38,7 +38,6 @@ translation_array = [
"アカウント",
"アカウント#0は仮定されます",
"アカウントインデックス",
- "シェアを追加",
"ウォレットのパスフレーズを追加または変更しますか?",
"%sにはカメラからの追加エントロピーが必要です",
"アドレス",
@@ -68,7 +67,6 @@ translation_array = [
"このアドレスがこのウォレットに属しているか確認しますか?",
"%d のアドレスを確認しましたが、一致するものはありませんでした.",
"SDカードを確認しています…",
- "シェアを消去",
"改ざんチェックコードの確認",
"データムの変換",
"変更先住所を特定できませんでした.",
@@ -76,7 +74,6 @@ translation_array = [
"テキストからQRコードを作成しますか?",
"作成されました:",
"現在の改ざんチェックコード",
- "現在のニーモニックとパスフレーズは保持されません。",
"カスタムQRコード",
"カスタムテキスト",
"カスタマイズする",
@@ -91,7 +88,6 @@ translation_array = [
"パスごとの深さ",
"導出パス",
"BIP85エントロピーを導出しますか?",
- "シェアを導出",
"ディスクリプタアドレス",
"デバイステスト",
"ディスプレイ",
@@ -154,6 +150,7 @@ translation_array = [
"高い手数料!",
"ID",
"IDはすでに存在します",
+ "この変更後にデバイスのディスプレイが動作しない場合、5秒後に以前の設定で自動的に再起動します.",
"インデックス",
"インプット(%d):",
"不十分なエントロピー!",
@@ -164,8 +161,6 @@ translation_array = [
"無効なウォレット:",
"反転する",
"反転した色",
- "読み込まれたすべてのシェアを消去します",
- "現在のキー、パスフレーズ、ディスクリプタを削除します。",
"暗号化されたKEF",
"キー",
"キーが提供されていません",
@@ -199,8 +194,8 @@ translation_array = [
"ミラーX座標",
"署名ファイルが欠落しています",
"Mnemonic",
+ "ニーモニックXOR",
"Mnemonicとパスフレーズは保持されます.",
- "ニーモニックは現在のニーモニック(SeedXOR)とXORされます。",
"修正されました:",
"ネイティブSegwit - 84が仮定されます",
"ネットワーク",
@@ -374,8 +369,10 @@ translation_array = [
"単語 %d",
"単語番号",
"単語",
+ "XOR結果",
+ "XOR With",
+ "XOR現在のニーモニックと別のニーモニック? (パスフレーズと記述子は破棄されます)",
"はい",
- "最大 %d 個のシェアを追加できます",
"ズームモード",
"バイナリ:",
"失敗",
diff --git a/src/krux/translations/ko.py b/src/krux/translations/ko.py
index d2e49b9..3007c6e 100644
--- a/src/krux/translations/ko.py
+++ b/src/krux/translations/ko.py
@@ -38,7 +38,6 @@ translation_array = [
"계정",
"계정 #0이 가정됩니다",
"계정 인덱스",
- "쉐어 추가",
"패스프레이즈를 추가하거나 변경하시겠습니까?",
"%s 에 필요한 카메라의 추가 엔트로피",
"주소",
@@ -68,7 +67,6 @@ translation_array = [
"해당 주소가 이 지갑에 속하는지 확인하시겠습니까?",
"일치하는 주소가 없는 %d 개를 확인했습니다.",
"SD 카드 확인 중…",
- "쉐어 정리",
"탬퍼 체크 코드 확인",
"날짜 변환",
"변경 주소를 확인할 수 없습니다.",
@@ -76,7 +74,6 @@ translation_array = [
"문자 메시지로 QR 코드를 만드시겠어요?",
"생성됨:",
"현재 탬퍼 체크 코드",
- "현재 니모닉과 패스프레이즈는 유지되지 않습니다.",
"사용자 지정 QR 코드",
"사용자 텍스트",
"사용자 정의",
@@ -91,7 +88,6 @@ translation_array = [
"Depth Per Pass",
"파생 경로",
"BIP85 엔트로피를 유독하시겠습니까?",
- "쉐어 파생",
"디스크립터 주소",
"장치 테스트",
"디스플레이",
@@ -154,6 +150,7 @@ translation_array = [
"수수료가 높습니다!",
"ID",
"아이디가 이미 존재합니다",
+ "이 변경 후에도 장치 디스플레이가 작동하지 않으면 5초 후에 이전 설정으로 자동으로 재부팅됩니다.",
"인덱스",
"Input (%d):",
"엔트로피가 충분하지 않습니다!",
@@ -164,8 +161,6 @@ translation_array = [
"지갑이 잘못되었습니다:",
"반전",
"반전된 색상",
- "로드된 모든 쉐어가 삭제됩니다",
- "현재 키, 패스프레이즈 및 디스크립터가 삭제됩니다.",
"KEF 암호화됨",
"키",
"키가 제공되지 않았습니다",
@@ -199,8 +194,8 @@ translation_array = [
"미러 X 좌표",
"서명 파일이 누락되었습니다",
"니모닉",
+ "니모닉 XOR",
"니모닉과 암호는 유지됩니다.",
- "니모닉은 현재 니모닉(SeedXOR)과 XOR 연산됩니다.",
"수정되었습니다:",
"네이티브 세그윗 - BIP84를 적용합니다",
"네트워크",
@@ -374,8 +369,10 @@ translation_array = [
"%d 단어",
"단어 번호(1-2048)",
"시드문구",
+ "XOR 결과",
+ "XOR With",
+ "다른 XOR 전류 니모닉? (패스프레이즈와 디스크립터가 폐기됩니다)",
"예",
- "최대 %d개의 쉐어를 추가할 수 있습니다",
"확대 모드",
"바이너리:",
"실패",
diff --git a/src/krux/translations/nl.py b/src/krux/translations/nl.py
index 9e04f9c..cab0979 100644
--- a/src/krux/translations/nl.py
+++ b/src/krux/translations/nl.py
@@ -38,7 +38,6 @@ translation_array = [
"Account",
"Account #0 zou worden aangenomen",
"Accountindex",
- "Een aandeel toevoegen",
"Wachtwoordzin voor portemonnee toevoegen of wijzigen?",
"Extra entropie van camera vereist voor %s",
"Adres",
@@ -68,7 +67,6 @@ translation_array = [
"Controleer of dit adres bij deze portemonnee hoort?",
"%d adressen gecontroleerd zonder overeenkomsten.",
"Controleren op SD-kaart…",
- "Aandelen opschonen",
"Bevestig de sabotagecontrolecode",
"Datum converteren",
"Kan adreswijziging niet bepalen.",
@@ -76,7 +74,6 @@ translation_array = [
"QR-code maken van tekst?",
"Aangemaakt:",
"Huidige sabotagecontrolecode",
- "De huidige mnemonic en wachtwoordzin worden niet behouden.",
"Aangepaste QR-code",
"Aangepaste tekst",
"Aanpassen",
@@ -91,7 +88,6 @@ translation_array = [
"Diepte per pas",
"Afleidingspad",
"BIP85-entropie afleiden?",
- "Aandelen afleiden",
"Descriptoradressen",
"Apparaattests",
"Weergave",
@@ -154,6 +150,7 @@ translation_array = [
"Hoge kosten!",
"ID",
"ID bestaat al",
+ "Als het scherm van uw apparaat na deze wijziging niet werkt, wordt het na 5 seconden automatisch opnieuw opgestart met de vorige instellingen.",
"Index",
"Invoer (%d):",
"Onvoldoende Entropie!",
@@ -164,8 +161,6 @@ translation_array = [
"Ongeldige portemonnee:",
"Omkeren",
"Omgekeerde kleuren",
- "Alle geladen aandelen worden verwijderd",
- "De huidige sleutel, wachtwoordzin en beschrijver worden verwijderd.",
"KEF versleuteld",
"Sleutel",
"Sleutel niet verstrekt",
@@ -199,8 +194,8 @@ translation_array = [
"X-coördinaten spiegelen",
"Handtekening bestand mist",
"Geheugensteun",
+ "Mnemonic XOR",
"Geheugensteun en wachtwoord worden bewaard.",
- "De mnemonics worden met de huidige mnemonic (SeedXOR) via XOR gecombineerd.",
"Aangepast:",
"Native Segwit - 84 zal worden gebruikt",
"Netwerk",
@@ -374,8 +369,10 @@ translation_array = [
"Woord %d",
"Woord nummers",
"Woorden",
+ "XOR-resultaat",
+ "XOR met",
+ "XOR huidig geheugensteuntje met een ander? (passphrase en descriptor worden weggegooid)",
"Yes",
- "U kunt maximaal %d aandelen toevoegen",
"Ingezoomde modus",
"binair:",
"mislukt",
diff --git a/src/krux/translations/pt.py b/src/krux/translations/pt.py
index 35ce69b..8127047 100644
--- a/src/krux/translations/pt.py
+++ b/src/krux/translations/pt.py
@@ -38,7 +38,6 @@ translation_array = [
"Conta",
"A conta #0 seria assumida",
"Índice da Conta",
- "Adicionar uma parte",
"Adicionar ou alterar a senha da carteira?",
"Entropia adicional da câmera é necessária para %s",
"Endereço",
@@ -68,7 +67,6 @@ translation_array = [
"Checar se o endereço pertence a esta carteira?",
"%d endereços checados sem correspondência.",
"Procurando por cartão SD…",
- "Limpar partes",
"Confirmar código de verificação de integridade",
"Converter dados",
"Não foi possível determinar endereços de troco.",
@@ -76,7 +74,6 @@ translation_array = [
"Criar código QR a partir de texto?",
"Criado:",
"Código atual de verificação de integridade",
- "A mnemônica atual e a senha não serão mantidas.",
"Código QR personalizado",
"Texto Personalizado",
"Personalizar",
@@ -91,7 +88,6 @@ translation_array = [
"Profundidade por passe",
"Caminho de Derivação",
"Derivar entropia BIP85?",
- "Derivar partes",
"Endereços do descritor",
"Testes do Dispositivo",
"Display",
@@ -154,6 +150,7 @@ translation_array = [
"Taxas altas!",
"ID",
"ID já existe",
+ "Se a tela do seu dispositivo não funcionar após essa alteração, ele será reiniciado automaticamente com as configurações anteriores após 5 segundos.",
"Índice",
"Entradas (%d):",
"Entropia insuficiente!",
@@ -164,8 +161,6 @@ translation_array = [
"Carteira inválida:",
"Inverter",
"Cores invertidas",
- "Todas as partes carregadas serão limpas",
- "A chave atual, a senha e o descritor serão excluídos.",
"KEF criptografado",
"Chave",
"A chave não foi fornecida",
@@ -199,8 +194,8 @@ translation_array = [
"Coordenadas X espelhadas",
"Arquivo de assinatura não encontrado",
"Mnemônico",
+ "XOR Mnemônico",
"Mnemônico e senha serão mantidos.",
- "As mnemônicas serão XORadas com a mnemônica atual (SeedXOR).",
"Alterado:",
"Segwit nativo - 84 seria assumido",
"Rede",
@@ -374,8 +369,10 @@ translation_array = [
"Palavra %d",
"Números das Palavras",
"Palavras",
+ "Resultado XOR",
+ "XOR com",
+ "XOR atual mnemônico com outro? (senha e descritor serão descartados)",
"Sim",
- "Você pode adicionar até %d partes",
"Modo ampliado",
"binário:",
"falha",
diff --git a/src/krux/translations/ru.py b/src/krux/translations/ru.py
index 8d9af0b..a728898 100644
--- a/src/krux/translations/ru.py
+++ b/src/krux/translations/ru.py
@@ -38,7 +38,6 @@ translation_array = [
"Учетная запись",
"Будет принят счет №0",
"Индекс счета",
- "Добавить долю",
"Добавить или изменить пароль кошелька?",
"Требуется дополнительная энтропия от камеры для %s",
"Адрес",
@@ -68,7 +67,6 @@ translation_array = [
"Проверить, что адрес принадлежит этому кошельку?",
"Проверено %d адресов без совпадений.",
"Проверка SD-карты…",
- "Очистить доли",
"Подтвердите код проверки вскрытия",
"Преобразовать датум",
"Не удалось определить адрес изменения.",
@@ -76,7 +74,6 @@ translation_array = [
"Создать QR-код из текста?",
"Создано:",
"Текущий код проверки вскрытия",
- "Текущая мнемоника и парольная фраза не будут сохранены.",
"Пользовательский QR-код",
"Произвольный текст",
"Настроить",
@@ -91,7 +88,6 @@ translation_array = [
"Глубина за Проход",
"Путь деривации",
"Вывести энтропию BIP85?",
- "Произвести доли",
"Адреса дескрипторов",
"Испытания устройства",
"Дисплеи",
@@ -154,6 +150,7 @@ translation_array = [
"Высокие комиссии!",
"Идентификатор",
"ID уже существует",
+ "Если после этого изменения дисплей устройства не работает, он автоматически перезагрузится с предыдущими настройками через 5 секунд.",
"Индекс",
"Входы (%d):",
"Недостаточная Энтропия!",
@@ -164,8 +161,6 @@ translation_array = [
"Неверный кошелек:",
"Инвертировать",
"Перевернутые цвета",
- "Все загруженные доли будут удалены",
- "Будут удалены текущий ключ, парольная фраза и дескриптор.",
"Зашифровано KEF",
"Ключ",
"Ключ не предоставлен",
@@ -199,8 +194,8 @@ translation_array = [
"Координаты зеркала X",
"Отсутствует файл подписи",
"Мнемоника",
+ "Мнемонический XOR",
"Мнемоника и парольная фраза будут сохранены.",
- "Мнемоника(и) будет(ут) объединена(ы) по XOR с текущей мнемоникой (SeedXOR).",
"Изменено:",
"Native Segwit - 84 будет принято",
"Сеть",
@@ -374,8 +369,10 @@ translation_array = [
"Слово %d",
"Числа Слов",
"Слова",
+ "Результат XOR",
+ "XOR с",
+ "XOR current mnemonic with another one? (парольная фраза и дескриптор будут отброшены)",
"Да",
- "Можно добавить до %d долей",
"Режим масштабирования",
"двоичный:",
"неудачно",
diff --git a/src/krux/translations/tr.py b/src/krux/translations/tr.py
index 0422469..0efac34 100644
--- a/src/krux/translations/tr.py
+++ b/src/krux/translations/tr.py
@@ -38,7 +38,6 @@ translation_array = [
"Hesap",
"#0 numaralı hesap varsayılacaktır",
"Hesap Endeksi",
- "Pay ekle",
"Cüzdan parolası eklensin mi veya değiştirilsin mi?",
"%s için kameradan gelen ek entropi gerekli",
"Adres",
@@ -68,7 +67,6 @@ translation_array = [
"Bu adresin, bu cüzdana ait olduğunu kontrol et?",
"Eşleşmeyen %d adres kontrol edildi.",
"SD kart kontrol ediliyor…",
- "Payları temizle",
"Kurcalama Kontrol Kodunu Onayla",
"Veriyi Dönüştür",
"Değişiklik adresi belirlenemedi.",
@@ -76,7 +74,6 @@ translation_array = [
"Metinden QR kodu oluşturulsun mu?",
"Oluşturuldu:",
"Mevcut Kurcalama Kontrol Kodu",
- "Geçerli anımsatıcı ve parola saklanmayacak.",
"Özel QR Kodu",
"Özel metin",
"Özelleştir",
@@ -91,7 +88,6 @@ translation_array = [
"Geçiş Başına Derinlik",
"Türetim Yolu",
"BIP85 entropisi türetilsin mi?",
- "Payları türet",
"Tanımlayıcı Adresler",
"Cihaz Testleri",
"Ekran",
@@ -154,6 +150,7 @@ translation_array = [
"Yüksek ücret!",
"ID",
"ID zaten var",
+ "Bu değişiklikten sonra cihazınızın ekranı çalışmazsa, 5 saniye sonra önceki ayarlarla otomatik olarak yeniden başlatılır.",
"Dizin",
"Girişler (%d):",
"Yetersiz entropi!",
@@ -164,8 +161,6 @@ translation_array = [
"Geçersiz cüzdan:",
"Ters Çevir",
"Ters Renkler",
- "Yüklenen tüm paylar temizlenecek",
- "Geçerli Anahtar, Parola ve Tanımlayıcı silinecek.",
"Kef Şifreli",
"Anahtar",
"Anahtar sağlanmadı",
@@ -199,8 +194,8 @@ translation_array = [
"Ayna X Koordinatları",
"İmza dosyası eksik",
"Mnemonic",
+ "Anımsatıcı XOR",
"Mnemonik ve parola tutulacaktır.",
- "Anımsatıcı(lar), mevcut anımsatıcı (SeedXOR) ile XOR yapılacak.",
"Değiştirildi:",
"Yerel Segwit - 84 varsayılacaktır",
"Ağ",
@@ -374,8 +369,10 @@ translation_array = [
"Kelime %d",
"Kelime Numaraları",
"Kelimeler",
+ "XOR Sonucu",
+ "XOR ile",
+ "XOR başka biriyle geçerli anımsatıcı? (parola ve tanımlayıcı atılacak)",
"Evet",
- "%d adede kadar pay ekleyebilirsiniz",
"Zoom Mod",
"ikili:",
"Kalınan: ",
diff --git a/src/krux/translations/vi.py b/src/krux/translations/vi.py
index 5f496cb..6423f52 100644
--- a/src/krux/translations/vi.py
+++ b/src/krux/translations/vi.py
@@ -38,7 +38,6 @@ translation_array = [
"Tài khoản",
"Tài khoản #0 sẽ được giả định",
"Chỉ mục tài khoản",
- "Thêm phần chia sẻ",
"Thêm hoặc thay đổi cụm mật khẩu ví?",
"Entropy bổ sung từ máy ảnh cần thiết cho %s",
"Địa chỉ",
@@ -68,7 +67,6 @@ translation_array = [
"Kiểm tra địa chỉ đó có thuộc về ví này không?",
"Đã kiểm tra %d địa chỉ không khớp.",
"Đang kiểm tra thẻ SD…",
- "Xóa phần chia sẻ",
"Xác nhận mã kiểm tra giả mạo",
"Chuyển đổi dữ liệu",
"Không thể xác định địa chỉ thay đổi.",
@@ -76,7 +74,6 @@ translation_array = [
"Tạo mã QR từ văn bản?",
"Tạo:",
"Mã kiểm tra giả mạo hiện tại",
- "Cụm từ ghi nhớ và mật khẩu hiện tại sẽ không được giữ lại.",
"Mã QR tùy chỉnh",
"Văn bản tùy chọn",
"Tùy chỉnh",
@@ -91,7 +88,6 @@ translation_array = [
"Độ sâu mỗi lần cắt CNC",
"Đường dẫn phái sinh",
"Suy ra entropy BIP85?",
- "Tạo phần chia sẻ",
"Địa chỉ người mô tả",
"Kiểm tra thiết bị",
"Hiển thị",
@@ -154,6 +150,7 @@ translation_array = [
"Phí cao!",
"ID",
"Id đã tồn tại",
+ "Nếu màn hình thiết bị của bạn không hoạt động sau khi thay đổi này, màn hình sẽ tự động khởi động lại với các cài đặt trước đó sau 5 giây.",
"Chỉ mục",
"Đầu vào (%d):",
"Entropy không đủ!",
@@ -164,8 +161,6 @@ translation_array = [
"Ví không hợp lệ:",
"Đảo ngược",
"Màu đảo ngược",
- "Tất cả các phần chia sẻ đã tải sẽ bị xóa",
- "Khóa hiện tại, mật khẩu và mô tả sẽ bị xóa.",
"Đã mã hóa KEF",
"Chìa khóa",
"Khóa không được cung cấp",
@@ -199,8 +194,8 @@ translation_array = [
"Tọa độ gương X",
"Thiếu tập tin chữ ký",
"Mã mnemonic",
+ "Mnemonic XOR",
"Từ gợi nhớ và cụm mật khẩu sẽ được lưu giữ.",
- "Cụm từ ghi nhớ sẽ được XOR với cụm từ ghi nhớ hiện tại (SeedXOR).",
"Đã sửa đổi:",
"Native Segwit - 84 sẽ được giả định",
"Mạng lưới",
@@ -374,8 +369,10 @@ translation_array = [
"Kí tự %d",
"Từ số",
"Từ ngữ",
+ "Kết quả XOR",
+ "XOR với",
+ "Ghi nhớ hiện tại của XOR với một cụm từ khác? (cụm mật khẩu và mô tả sẽ bị loại bỏ)",
"Đúng",
- "Bạn có thể thêm tối đa %d phần chia sẻ",
"Chế độ thu phóng",
"nhị phân:",
"trượt",
diff --git a/src/krux/translations/zh.py b/src/krux/translations/zh.py
index dbd29a9..44ba6c2 100644
--- a/src/krux/translations/zh.py
+++ b/src/krux/translations/zh.py
@@ -38,7 +38,6 @@ translation_array = [
"账户",
"将假定为账户 #0",
"账户索引",
- "添加份额",
"添加或更改钱包密码?",
"%s需要摄像头的额外熵",
"地址",
@@ -68,7 +67,6 @@ translation_array = [
"检查该地址是否属于此钱包?",
"已检查 %d 个不匹配的地址.",
"检查卡…",
- "清理份额",
"确认防篡改检查码",
"转换基准",
"无法确定更改地址.",
@@ -76,7 +74,6 @@ translation_array = [
"从短信创建二维码?",
"已创建:",
"当前防篡改检查码",
- "当前助记词和密码短语将不会被保留。",
"自定义二维码",
"自定义文本",
"自定义",
@@ -91,7 +88,6 @@ translation_array = [
"每次通过的深度",
"源路径",
"导出BIP85熵?",
- "派生份额",
"描述符地址",
"设备测试",
"显示",
@@ -154,6 +150,7 @@ translation_array = [
"高费用!",
"ID",
"ID 已存在",
+ "如果您的设备显示屏在此更改后无法正常工作,它将在5秒后使用以前的设置自动重新启动.",
"索引",
"输入 (%d):",
"熵不足!",
@@ -164,8 +161,6 @@ translation_array = [
"无效钱包:",
"反转",
"反转颜色",
- "将清除所有已加载的份额",
- "将删除当前密钥、密码短语和描述符。",
"KEF加密",
"密钥",
"未提供密钥",
@@ -199,8 +194,8 @@ translation_array = [
"镜像X坐标",
"缺少签名文件",
"助记词",
+ "助记符异或",
"助记词和密码将被保留.",
- "助记词将与当前助记词(SeedXOR)进行异或运算。",
"修改时间:",
"假定为原生 Segwit - 84",
"网络",
@@ -374,8 +369,10 @@ translation_array = [
"词 %d",
"单词序号",
"单词",
+ "XOR结果",
+ "XOR With",
+ "XOR当前助记符与其他助记符? (密码短语和描述符将被丢弃)",
"是",
- "您最多可以添加 %d 个份额",
"放大模式",
"二进制:",
"失败",
diff --git a/tests/pages/home_pages/test_mnemonic_xor.py b/tests/pages/home_pages/test_mnemonic_xor.py
index d6d4e8a..9d18cb4 100644
--- a/tests/pages/home_pages/test_mnemonic_xor.py
+++ b/tests/pages/home_pages/test_mnemonic_xor.py
@@ -176,7 +176,7 @@ def test_menu_load_and_back(mocker, m5stickv, tdata):
wallet = Wallet(key)
ctx = create_ctx(mocker, case, wallet)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
assert ctx.wallet.key.fingerprint.hex() == "a70e2c26"
assert ctx.input.wait_for_button.call_count == len(case)
@@ -233,7 +233,7 @@ def test_menu_load_qrcode_and_back(mocker, amigo, tdata):
)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
assert ctx.wallet.key.fingerprint.hex() == "a70e2c26"
assert ctx.input.wait_for_button.call_count == len(case)
@@ -336,7 +336,7 @@ def test_load_from_qrcode(mocker, amigo, tdata):
)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
assert ctx.wallet.key.mnemonic == case[1][2]
assert ctx.wallet.key.fingerprint.hex() == case[2][1]
@@ -442,7 +442,7 @@ def test_load_from_qrcode_with_hide_mnemonic(mocker, amigo, tdata):
)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
assert ctx.wallet.key.mnemonic == case[1][2]
assert ctx.wallet.key.fingerprint.hex() == case[2][1]
@@ -561,7 +561,7 @@ def test_export_from_words(mocker, amigo, tdata):
m = MnemonicXOR(ctx)
mocker.patch.object(m, "capture_from_keypad", side_effect=words)
mocker.spy(m, "xor_with_current_mnemonic")
- m.load()
+ m.load_key()
m.xor_with_current_mnemonic.assert_called_once_with(case[1][1])
assert ctx.wallet.key.mnemonic == case[1][2]
@@ -604,7 +604,7 @@ def test_export_xor_to_same_mnemonic_from_qrcode(mocker, amigo, tdata):
)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
ctx.display.draw_centered_text.assert_has_calls(
[mocker.call("Error:\nValueError('Low entropy mnemonic')", 248)],
any_order=True,
@@ -646,7 +646,7 @@ def test_export_xor_to_inverted_mnemonic_from_qrcode(mocker, amigo, tdata):
)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
ctx.display.draw_centered_text.assert_has_calls(
[mocker.call("Error:\nValueError('Low entropy mnemonic')", 248)],
any_order=True,
@@ -690,8 +690,26 @@ def test_export_xor_low_entropy_mnemonic_from_qrcode(mocker, amigo, tdata):
)
m = MnemonicXOR(ctx)
- m.load()
+ m.load_key()
ctx.display.draw_centered_text.assert_has_calls(
[mocker.call("Error:\nValueError('Low entropy mnemonic')", 248)],
any_order=True,
)
+
+
+def test_mnemonic_len(mocker, m5stickv, tdata):
+ from krux.pages.home_pages.mnemonic_xor import MnemonicXOR
+ from krux.input import BUTTON_ENTER
+ from krux.key import Key, TYPE_SINGLESIG
+ from krux.wallet import Wallet
+ from embit.networks import NETWORKS
+
+ key = Key(tdata.TEST_XOR_12_WORD_MNEMONIC_1, TYPE_SINGLESIG, NETWORKS["test"])
+ wallet = Wallet(key)
+ ctx = create_ctx(mocker, [BUTTON_ENTER, BUTTON_ENTER], wallet)
+ m = MnemonicXOR(ctx)
+ assert m.choose_len_mnemonic() == 12
+
+ key = Key(tdata.TEST_XOR_24_WORD_MNEMONIC_1, TYPE_SINGLESIG, NETWORKS["test"])
+ ctx.wallet = Wallet(key)
+ assert m.choose_len_mnemonic() == 24
Why this scored 24/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.