|
|
|
@ -4,8 +4,12 @@ Revealer |
|
|
|
Do you have something to hide? |
|
|
|
Do you have something to hide? |
|
|
|
Secret backup plug-in for the electrum wallet. |
|
|
|
Secret backup plug-in for the electrum wallet. |
|
|
|
|
|
|
|
|
|
|
|
Tiago Romagnani Silveira, 2017 |
|
|
|
Copyright: |
|
|
|
|
|
|
|
2017 Tiago Romagnani Silveira |
|
|
|
|
|
|
|
2023 Soren Stoutner <soren@stoutner.com> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Distributed under the MIT software license, see the accompanying |
|
|
|
|
|
|
|
file LICENCE or http://www.opensource.org/licenses/mit-license.php |
|
|
|
|
|
|
|
|
|
|
|
''' |
|
|
|
''' |
|
|
|
|
|
|
|
|
|
|
|
@ -96,42 +100,55 @@ class Plugin(RevealerPlugin): |
|
|
|
self.update_wallet_name(self.wallet) |
|
|
|
self.update_wallet_name(self.wallet) |
|
|
|
self.user_input = False |
|
|
|
self.user_input = False |
|
|
|
|
|
|
|
|
|
|
|
self.d = WindowModalDialog(window, "Setup Dialog") |
|
|
|
self.d = WindowModalDialog(window, "Revealer Visual Cryptography Plugin - Select Noise File") |
|
|
|
self.d.setMinimumWidth(500) |
|
|
|
|
|
|
|
self.d.setMinimumHeight(210) |
|
|
|
|
|
|
|
self.d.setMaximumHeight(320) |
|
|
|
|
|
|
|
self.d.setContentsMargins(11,11,1,1) |
|
|
|
self.d.setContentsMargins(11,11,1,1) |
|
|
|
|
|
|
|
|
|
|
|
self.hbox = QHBoxLayout(self.d) |
|
|
|
# Create an HBox layout. The logo will be on the left and the rest of the dialog on the right. |
|
|
|
vbox = QVBoxLayout() |
|
|
|
hbox_layout = QHBoxLayout(self.d) |
|
|
|
logo = QLabel() |
|
|
|
|
|
|
|
self.hbox.addWidget(logo) |
|
|
|
# Create the logo label. |
|
|
|
logo.setPixmap(QPixmap(icon_path('revealer.png'))) |
|
|
|
logo_label = QLabel() |
|
|
|
logo.setAlignment(Qt.AlignLeft) |
|
|
|
|
|
|
|
self.hbox.addSpacing(16) |
|
|
|
# Set the logo label pixmap. |
|
|
|
vbox.addWidget(WWLabel("<b>"+_("Revealer Visual Cryptography Plugin")+"</b><br><br>" |
|
|
|
logo_label.setPixmap(QPixmap(icon_path('revealer.png'))) |
|
|
|
+_("To encrypt a secret, first create or load noise.")+"<br/>")) |
|
|
|
|
|
|
|
vbox.addSpacing(7) |
|
|
|
# Align the logo label to the top left. |
|
|
|
bcreate = QPushButton(_("Create a new Revealer")) |
|
|
|
logo_label.setAlignment(Qt.AlignLeft) |
|
|
|
bcreate.setMaximumWidth(181) |
|
|
|
|
|
|
|
bcreate.setDefault(True) |
|
|
|
# Create a VBox layout for the main contents of the dialog. |
|
|
|
vbox.addWidget(bcreate, Qt.AlignCenter) |
|
|
|
vbox_layout = QVBoxLayout() |
|
|
|
self.load_noise = ScanQRTextEdit(config=self.config) |
|
|
|
|
|
|
|
self.load_noise.setTabChangesFocus(True) |
|
|
|
# Populate the HBox layout with spacing between the two columns. |
|
|
|
self.load_noise.textChanged.connect(self.on_edit) |
|
|
|
hbox_layout.addWidget(logo_label) |
|
|
|
self.load_noise.setMaximumHeight(33) |
|
|
|
hbox_layout.addSpacing(16) |
|
|
|
self.hbox.addLayout(vbox) |
|
|
|
hbox_layout.addLayout(vbox_layout) |
|
|
|
vbox.addWidget(WWLabel(_("or type an existing revealer code below and click 'next':"))) |
|
|
|
|
|
|
|
vbox.addWidget(self.load_noise) |
|
|
|
# Create the labels. |
|
|
|
vbox.addSpacing(3) |
|
|
|
create_or_load_noise_file_label = QLabel(_("To encrypt a secret, you must first create or load a noise file.")) |
|
|
|
|
|
|
|
instructions_label = QLabel(_("Click the button above or type an existing revealer code in the box below.")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Allow users to select text in the labels. |
|
|
|
|
|
|
|
create_or_load_noise_file_label.setTextInteractionFlags(Qt.TextSelectableByMouse) |
|
|
|
|
|
|
|
instructions_label.setTextInteractionFlags(Qt.TextSelectableByMouse) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the buttons. |
|
|
|
|
|
|
|
create_button = QPushButton(_("Create a new Revealer noise file")) |
|
|
|
self.next_button = QPushButton(_("Next"), self.d) |
|
|
|
self.next_button = QPushButton(_("Next"), self.d) |
|
|
|
self.next_button.setEnabled(False) |
|
|
|
|
|
|
|
vbox.addLayout(Buttons(self.next_button)) |
|
|
|
|
|
|
|
self.next_button.clicked.connect(self.d.close) |
|
|
|
|
|
|
|
self.next_button.clicked.connect(partial(self.cypherseed_dialog, window)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Calculate the desired width of the create button |
|
|
|
|
|
|
|
create_button_width = create_button.fontMetrics().boundingRect(create_button.text()).width() + 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the create button width. |
|
|
|
|
|
|
|
create_button.setMaximumWidth(create_button_width) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the create button to be the default. |
|
|
|
|
|
|
|
create_button.setDefault(True) |
|
|
|
|
|
|
|
|
|
|
|
def mk_digital(): |
|
|
|
# Initially disable the next button. |
|
|
|
|
|
|
|
self.next_button.setEnabled(False) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Define the create noise file function. |
|
|
|
|
|
|
|
def create_noise_file(): |
|
|
|
try: |
|
|
|
try: |
|
|
|
self.make_digital(self.d) |
|
|
|
self.make_digital(self.d) |
|
|
|
except Exception: |
|
|
|
except Exception: |
|
|
|
@ -139,11 +156,36 @@ class Plugin(RevealerPlugin): |
|
|
|
else: |
|
|
|
else: |
|
|
|
self.cypherseed_dialog(window) |
|
|
|
self.cypherseed_dialog(window) |
|
|
|
|
|
|
|
|
|
|
|
bcreate.clicked.connect(mk_digital) |
|
|
|
# Handle clicks on the buttons. |
|
|
|
|
|
|
|
create_button.clicked.connect(create_noise_file) |
|
|
|
|
|
|
|
self.next_button.clicked.connect(self.d.close) |
|
|
|
|
|
|
|
self.next_button.clicked.connect(partial(self.cypherseed_dialog, window)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the noise scan QR text edit. |
|
|
|
|
|
|
|
self.noise_scan_qr_textedit = ScanQRTextEdit(config=self.config) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make tabs change focus from the text edit instead of inserting a tab into the field. |
|
|
|
|
|
|
|
self.noise_scan_qr_textedit.setTabChangesFocus(True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Update the UI when the text changes. |
|
|
|
|
|
|
|
self.noise_scan_qr_textedit.textChanged.connect(self.on_edit) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Populate the VBox layout. |
|
|
|
|
|
|
|
vbox_layout.addWidget(create_or_load_noise_file_label) |
|
|
|
|
|
|
|
vbox_layout.addWidget(create_button, alignment=Qt.AlignCenter) |
|
|
|
|
|
|
|
vbox_layout.addWidget(instructions_label) |
|
|
|
|
|
|
|
vbox_layout.addWidget(self.noise_scan_qr_textedit) |
|
|
|
|
|
|
|
vbox_layout.addLayout(Buttons(self.next_button)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add stretches to the end of the layouts to prevent the contents from spreading when the dialog is enlarged. |
|
|
|
|
|
|
|
hbox_layout.addStretch(1) |
|
|
|
|
|
|
|
vbox_layout.addStretch(1) |
|
|
|
|
|
|
|
|
|
|
|
return bool(self.d.exec_()) |
|
|
|
return bool(self.d.exec_()) |
|
|
|
|
|
|
|
|
|
|
|
def get_noise(self): |
|
|
|
def get_noise(self): |
|
|
|
text = self.load_noise.text() |
|
|
|
# Get the text from the scan QR text edit. |
|
|
|
|
|
|
|
text = self.noise_scan_qr_textedit.text() |
|
|
|
return ''.join(text.split()).lower() |
|
|
|
return ''.join(text.split()).lower() |
|
|
|
|
|
|
|
|
|
|
|
def on_edit(self): |
|
|
|
def on_edit(self): |
|
|
|
@ -195,17 +237,34 @@ class Plugin(RevealerPlugin): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def customtxt_limits(self): |
|
|
|
def customtxt_limits(self): |
|
|
|
txt = self.text.text() |
|
|
|
txt = self.custom_secret_scan_qr_textedit.text() |
|
|
|
self.max_chars.setVisible(False) |
|
|
|
self.custom_secret_character_count_label.setText(f"({len(txt)}/{self.MAX_PLAINTEXT_LEN})") |
|
|
|
self.char_count.setText(f"({len(txt)}/{self.MAX_PLAINTEXT_LEN})") |
|
|
|
|
|
|
|
if len(txt)>0: |
|
|
|
# Hide the custom secret maximum characters warning label. |
|
|
|
self.ctext.setEnabled(True) |
|
|
|
self.custom_secret_maximum_characters_warning_label.setVisible(False) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Update the status of the encrypt custom secret button. |
|
|
|
|
|
|
|
self.encrypt_custom_secret_button.setEnabled(len(txt)>0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Check to make sure the length of the text has not exceeded the limit. |
|
|
|
if len(txt) > self.MAX_PLAINTEXT_LEN: |
|
|
|
if len(txt) > self.MAX_PLAINTEXT_LEN: |
|
|
|
self.text.setPlainText(txt[:self.MAX_PLAINTEXT_LEN]) |
|
|
|
# Truncate the text to the maximum limit. |
|
|
|
self.max_chars.setVisible(True) |
|
|
|
self.custom_secret_scan_qr_textedit.setPlainText(txt[:self.MAX_PLAINTEXT_LEN]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the text cursor. |
|
|
|
|
|
|
|
textCursor = self.custom_secret_scan_qr_textedit.textCursor() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Move the cursor position to the end (setting the text above automatically moves the cursor to the beginning, which is undesirable) |
|
|
|
|
|
|
|
textCursor.movePosition(textCursor.End) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the text cursor with the corrected position. |
|
|
|
|
|
|
|
self.custom_secret_scan_qr_textedit.setTextCursor(textCursor) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Display the custom secret maximum characters warning label. |
|
|
|
|
|
|
|
self.custom_secret_maximum_characters_warning_label.setVisible(True) |
|
|
|
|
|
|
|
|
|
|
|
def t(self): |
|
|
|
def t(self): |
|
|
|
self.txt = self.text.text() |
|
|
|
self.txt = self.custom_secret_scan_qr_textedit.text() |
|
|
|
self.seed_img(is_seed=False) |
|
|
|
self.seed_img(is_seed=False) |
|
|
|
|
|
|
|
|
|
|
|
def warn_old_revealer(self): |
|
|
|
def warn_old_revealer(self): |
|
|
|
@ -223,55 +282,99 @@ class Plugin(RevealerPlugin): |
|
|
|
def cypherseed_dialog(self, window): |
|
|
|
def cypherseed_dialog(self, window): |
|
|
|
self.warn_old_revealer() |
|
|
|
self.warn_old_revealer() |
|
|
|
|
|
|
|
|
|
|
|
d = WindowModalDialog(window, "Encryption Dialog") |
|
|
|
d = WindowModalDialog(window, "Revealer Visual Cryptography Plugin - Encryption Data") |
|
|
|
d.setMinimumWidth(500) |
|
|
|
|
|
|
|
d.setMinimumHeight(210) |
|
|
|
|
|
|
|
d.setMaximumHeight(450) |
|
|
|
|
|
|
|
d.setContentsMargins(11, 11, 1, 1) |
|
|
|
d.setContentsMargins(11, 11, 1, 1) |
|
|
|
self.c_dialog = d |
|
|
|
self.c_dialog = d |
|
|
|
|
|
|
|
|
|
|
|
hbox = QHBoxLayout(d) |
|
|
|
# Create an HBox layout. The logo will be on the left and the rest of the dialog on the right. |
|
|
|
self.vbox = QVBoxLayout() |
|
|
|
hbox_layout = QHBoxLayout(d) |
|
|
|
logo = QLabel() |
|
|
|
|
|
|
|
hbox.addWidget(logo) |
|
|
|
# Create the logo label. |
|
|
|
logo.setPixmap(QPixmap(icon_path('revealer.png'))) |
|
|
|
logo_label = QLabel() |
|
|
|
logo.setAlignment(Qt.AlignLeft) |
|
|
|
|
|
|
|
hbox.addSpacing(16) |
|
|
|
# Set the logo label pixmap. |
|
|
|
self.vbox.addWidget(WWLabel("<b>" + _("Revealer Visual Cryptography Plugin") + "</b><br><br>" |
|
|
|
logo_label.setPixmap(QPixmap(icon_path('revealer.png'))) |
|
|
|
+ _("Ready to encrypt for revealer {}") |
|
|
|
|
|
|
|
.format(self.versioned_seed.version+'_'+self.versioned_seed.checksum))) |
|
|
|
# Align the logo label to the top left. |
|
|
|
self.vbox.addSpacing(11) |
|
|
|
logo_label.setAlignment(Qt.AlignLeft) |
|
|
|
hbox.addLayout(self.vbox) |
|
|
|
|
|
|
|
grid = QGridLayout() |
|
|
|
# Create a VBox layout for the main contents of the dialog. |
|
|
|
self.vbox.addLayout(grid) |
|
|
|
vbox_layout = QVBoxLayout() |
|
|
|
|
|
|
|
|
|
|
|
cprint = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name)) |
|
|
|
# Populate the HBox layout. |
|
|
|
cprint.setMaximumWidth(250) |
|
|
|
hbox_layout.addWidget(logo_label) |
|
|
|
cprint.clicked.connect(partial(self.seed_img, True)) |
|
|
|
hbox_layout.addSpacing(16) |
|
|
|
self.vbox.addWidget(cprint) |
|
|
|
hbox_layout.addLayout(vbox_layout) |
|
|
|
self.vbox.addSpacing(1) |
|
|
|
|
|
|
|
self.vbox.addWidget(WWLabel("<b>"+_("OR")+"</b> "+_("type a custom alphanumerical secret below:"))) |
|
|
|
# Create the labels. |
|
|
|
self.text = ScanQRTextEdit(config=self.config) |
|
|
|
ready_to_encrypt_label = QLabel(_("Ready to encrypt for revealer {}.").format(self.versioned_seed.version+'_'+self.versioned_seed.checksum)) |
|
|
|
self.text.setTabChangesFocus(True) |
|
|
|
instructions_label = QLabel(_("Click the button above to encrypt the seed or type a custom alphanumerical secret below.")) |
|
|
|
self.text.setMaximumHeight(70) |
|
|
|
self.custom_secret_character_count_label = QLabel(f"(0/{self.MAX_PLAINTEXT_LEN})") |
|
|
|
self.text.textChanged.connect(self.customtxt_limits) |
|
|
|
self.custom_secret_maximum_characters_warning_label = QLabel("<font color='red'>" |
|
|
|
self.vbox.addWidget(self.text) |
|
|
|
+ _("This version supports a maximum of {} characters.").format(self.MAX_PLAINTEXT_LEN) |
|
|
|
self.char_count = WWLabel("") |
|
|
|
+"</font>") |
|
|
|
self.char_count.setAlignment(Qt.AlignRight) |
|
|
|
one_time_pad_warning_label = QLabel("<b>" + _("Warning ") + "</b>: " + _("each Revealer is a one-time-pad, use it for a single secret.")) |
|
|
|
self.vbox.addWidget(self.char_count) |
|
|
|
|
|
|
|
self.max_chars = WWLabel("<font color='red'>" |
|
|
|
# Allow users to select text in the labels. |
|
|
|
+ _("This version supports a maximum of {} characters.").format(self.MAX_PLAINTEXT_LEN) |
|
|
|
ready_to_encrypt_label.setTextInteractionFlags(Qt.TextSelectableByMouse) |
|
|
|
+"</font>") |
|
|
|
instructions_label.setTextInteractionFlags(Qt.TextSelectableByMouse) |
|
|
|
self.vbox.addWidget(self.max_chars) |
|
|
|
self.custom_secret_character_count_label.setTextInteractionFlags(Qt.TextSelectableByMouse) |
|
|
|
self.max_chars.setVisible(False) |
|
|
|
self.custom_secret_maximum_characters_warning_label |
|
|
|
self.ctext = QPushButton(_("Encrypt custom secret")) |
|
|
|
one_time_pad_warning_label.setTextInteractionFlags(Qt.TextSelectableByMouse) |
|
|
|
self.ctext.clicked.connect(self.t) |
|
|
|
|
|
|
|
self.vbox.addWidget(self.ctext) |
|
|
|
# Align the custom secret character count label to the right. |
|
|
|
self.ctext.setEnabled(False) |
|
|
|
self.custom_secret_character_count_label.setAlignment(Qt.AlignRight) |
|
|
|
self.vbox.addSpacing(11) |
|
|
|
|
|
|
|
self.vbox.addLayout(Buttons(CloseButton(d))) |
|
|
|
# Initially hide the custom secret character count label. |
|
|
|
self.vbox.addWidget( |
|
|
|
self.custom_secret_maximum_characters_warning_label.setVisible(False) |
|
|
|
QLabel("<br>"+"<b>" + _("Warning ") + "</b>: " + _("each Revealer is a one-time-pad, use it for a single secret."))) |
|
|
|
|
|
|
|
|
|
|
|
# Create the buttons. |
|
|
|
|
|
|
|
encrypt_seed_button = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name)) |
|
|
|
|
|
|
|
self.encrypt_custom_secret_button = QPushButton(_("Encrypt custom secret")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Calculate the desired width of the buttons. |
|
|
|
|
|
|
|
encrypt_seed_button_width = encrypt_seed_button.fontMetrics().boundingRect(encrypt_seed_button.text()).width() + 40 |
|
|
|
|
|
|
|
encrypt_custom_secret_button_width = self.encrypt_custom_secret_button.fontMetrics().boundingRect(self.encrypt_custom_secret_button.text()).width() + 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the button widths. |
|
|
|
|
|
|
|
encrypt_seed_button.setMaximumWidth(encrypt_seed_button_width) |
|
|
|
|
|
|
|
self.encrypt_custom_secret_button.setMaximumWidth(encrypt_custom_secret_button_width) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the encrypt seed button to be the default. |
|
|
|
|
|
|
|
encrypt_seed_button.setDefault(True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Initially disable the encrypt custom secret button. |
|
|
|
|
|
|
|
self.encrypt_custom_secret_button.setEnabled(False) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Handle clicks on the buttons. |
|
|
|
|
|
|
|
encrypt_seed_button.clicked.connect(partial(self.seed_img, True)) |
|
|
|
|
|
|
|
self.encrypt_custom_secret_button.clicked.connect(self.t) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the custom secret scan QR text edit. |
|
|
|
|
|
|
|
self.custom_secret_scan_qr_textedit = ScanQRTextEdit(config=self.config) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make tabs change focus from the text edit instead of inserting a tab into the field. |
|
|
|
|
|
|
|
self.custom_secret_scan_qr_textedit.setTabChangesFocus(True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Update the UI when the custom secret text changes. |
|
|
|
|
|
|
|
self.custom_secret_scan_qr_textedit.textChanged.connect(self.customtxt_limits) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Populate the VBox layout. |
|
|
|
|
|
|
|
vbox_layout.addWidget(ready_to_encrypt_label) |
|
|
|
|
|
|
|
vbox_layout.addWidget(encrypt_seed_button, alignment=Qt.AlignCenter) |
|
|
|
|
|
|
|
vbox_layout.addWidget(instructions_label) |
|
|
|
|
|
|
|
vbox_layout.addWidget(self.custom_secret_scan_qr_textedit) |
|
|
|
|
|
|
|
vbox_layout.addWidget(self.custom_secret_character_count_label) |
|
|
|
|
|
|
|
vbox_layout.addWidget(self.custom_secret_maximum_characters_warning_label) |
|
|
|
|
|
|
|
vbox_layout.addWidget(self.encrypt_custom_secret_button, alignment=Qt.AlignCenter) |
|
|
|
|
|
|
|
vbox_layout.addSpacing(40) |
|
|
|
|
|
|
|
vbox_layout.addWidget(one_time_pad_warning_label) |
|
|
|
|
|
|
|
vbox_layout.addLayout(Buttons(CloseButton(d))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add stretches to the end of the layouts to prevent the contents from spreading when the dialog is enlarged. |
|
|
|
|
|
|
|
hbox_layout.addStretch(1) |
|
|
|
|
|
|
|
vbox_layout.addStretch(1) |
|
|
|
|
|
|
|
|
|
|
|
return bool(d.exec_()) |
|
|
|
return bool(d.exec_()) |
|
|
|
|
|
|
|
|
|
|
|
def update_wallet_name(self, name): |
|
|
|
def update_wallet_name(self, name): |
|
|
|
|