mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-23 10:11:52 +03:00
Merge pull request #98 from tycho/add-hmac-sha256-gui.
This commit is contained in:
commit
db19508e77
@ -30,7 +30,7 @@ from __future__ import print_function
|
||||
|
||||
from .. import __version__
|
||||
from ..core.ccid import open_scard
|
||||
from ..core.standard import TYPE_HOTP, TYPE_TOTP
|
||||
from ..core.standard import ALG_SHA1, ALG_SHA256, TYPE_HOTP, TYPE_TOTP
|
||||
from ..core.utils import parse_uri
|
||||
from ..core.exc import NoSpaceError
|
||||
from .keystore import get_keystore
|
||||
@ -136,23 +136,44 @@ def show(ctx, query, slot1, slot2, timestamp):
|
||||
@click.option('-S', '--destination', type=click.IntRange(0, 2), default=0)
|
||||
@click.option('-N', '--name', required=False, help='Credential name.')
|
||||
@click.option('-A', '--oath-type', type=click.Choice(['totp', 'hotp']),
|
||||
default='totp', help='OATH algorithm.')
|
||||
default='totp', help='Specify whether this is a time or counter-based OATH credential.')
|
||||
@click.option('-D', '--digits', type=click.Choice(['6', '8']), default='6',
|
||||
callback=lambda c, p, v: int(v), help='Number of digits.')
|
||||
@click.option('-H', '--hmac-algorithm', type=click.Choice(['SHA1', 'SHA256']), default='SHA1',
|
||||
help='HMAC algorithm for OTP generation.')
|
||||
@click.option('-I', '--imf', type=int, default=0, help='Initial moving factor.')
|
||||
@click.option('-T', '--touch', is_flag=True, help='Require touch.')
|
||||
@click.pass_context
|
||||
def put(ctx, key, destination, name, oath_type, digits, imf, touch):
|
||||
def put(ctx, key, destination, name, oath_type, hmac_algorithm, digits, imf, touch):
|
||||
"""
|
||||
Stores a new OATH credential in the YubiKey.
|
||||
"""
|
||||
if key.startswith('otpauth://'):
|
||||
parsed = parse_uri(key)
|
||||
key = parsed['secret']
|
||||
name = name or parsed.get('name')
|
||||
name = parsed.get('name')
|
||||
oath_type = parsed.get('type')
|
||||
digits = digits or int(parsed.get('digits', '6'))
|
||||
imf = imf or int(parsed.get('counter', '0'))
|
||||
hmac_algorithm = parsed.get('algorithm', 'SHA1').upper()
|
||||
digits = int(parsed.get('digits', '6'))
|
||||
imf = int(parsed.get('counter', '0'))
|
||||
|
||||
if oath_type not in ['totp', 'hotp']:
|
||||
ctx.fail('Invalid OATH credential type')
|
||||
|
||||
if hmac_algorithm == 'SHA1':
|
||||
algo = ALG_SHA1
|
||||
elif hmac_algorithm == 'SHA256':
|
||||
algo = ALG_SHA256
|
||||
else:
|
||||
ctx.fail('Invalid HMAC algorithm')
|
||||
|
||||
if digits == 5 and name.startswith('Steam:'):
|
||||
# Steam is a special case where we allow the otpauth URI to contain a 'digits'
|
||||
# value of '5'.
|
||||
digits = 6
|
||||
|
||||
if digits not in [6, 8]:
|
||||
ctx.fail('Invalid number of digits for OTP')
|
||||
|
||||
digits = digits or 6
|
||||
unpadded = key.upper()
|
||||
@ -165,7 +186,7 @@ def put(ctx, key, destination, name, oath_type, digits, imf, touch):
|
||||
oath_type = TYPE_TOTP if oath_type == 'totp' else TYPE_HOTP
|
||||
try:
|
||||
controller.add_cred(dev, name, key, oath_type, digits=digits,
|
||||
imf=imf, require_touch=touch)
|
||||
imf=imf, algo=algo, require_touch=touch)
|
||||
except NoSpaceError:
|
||||
ctx.fail('There is not enough space to add another credential on your device.'
|
||||
'To create free space to add a new credential, delete those you no longer need.')
|
||||
|
@ -221,6 +221,7 @@ class YubiOathApplication(qt.Application):
|
||||
self._controller.add_cred(
|
||||
dialog.name, dialog.key, oath_type=dialog.oath_type,
|
||||
digits=dialog.n_digits,
|
||||
algo=dialog.algorithm,
|
||||
require_touch=dialog.require_touch)
|
||||
except NoSpaceError:
|
||||
QtGui.QMessageBox.critical(self.window, m.no_space, m.no_space_desc)
|
||||
|
@ -73,6 +73,7 @@ cred_key = "Secret key (base32)"
|
||||
cred_type = "Credential type"
|
||||
cred_totp = "Time based (TOTP)"
|
||||
cred_hotp = "Counter based (HOTP)"
|
||||
algorithm = "Algorithm"
|
||||
invalid_name = "Invalid name"
|
||||
invalid_name_desc = "Name must be at least 3 characters"
|
||||
invalid_key = "Invalid key"
|
||||
@ -111,6 +112,13 @@ qr_not_found_desc = "No usable QR code detected. Make sure the QR code is " \
|
||||
qr_not_supported = "Credential not supported"
|
||||
qr_not_supported_desc = "This credential type is not supported for slot " \
|
||||
"based usage."
|
||||
qr_invalid_type = "Invalid OTP type"
|
||||
qr_invalid_type_desc = "Only TOTP and HOTP types are supported."
|
||||
qr_invalid_digits = "Invalid number of digits"
|
||||
qr_invalid_digits_desc = "An OTP may only contain 6 or 8 digits."
|
||||
qr_invalid_algo = "Unsupported algorithm"
|
||||
qr_invalid_algo_desc = "SHA1 and SHA256 are the only supported OTP algorithms " \
|
||||
"at this time."
|
||||
tt_slot_enabled_1 = "Check to calculate TOTP codes using the YubiKey " \
|
||||
"standard slot %d credential."
|
||||
tt_num_digits = "The number of digits to show for the credential."
|
||||
|
@ -25,7 +25,7 @@
|
||||
# for the parts of OpenSSL used as well as that of the covered work.
|
||||
|
||||
from yubioath.yubicommon import qt
|
||||
from ...core.standard import TYPE_TOTP, TYPE_HOTP
|
||||
from ...core.standard import ALG_SHA1, ALG_SHA256, TYPE_TOTP, TYPE_HOTP
|
||||
from ...core.utils import parse_uri
|
||||
from .. import messages as m
|
||||
from ..qrparse import parse_qr_codes
|
||||
@ -99,6 +99,10 @@ class AddCredDialog(qt.Dialog):
|
||||
self._n_digits.addItems(['6', '8'])
|
||||
layout.addRow(m.n_digits, self._n_digits)
|
||||
|
||||
self._algorithm = QtGui.QComboBox()
|
||||
self._algorithm.addItems(['SHA-1', 'SHA-256'])
|
||||
layout.addRow(m.algorithm, self._algorithm)
|
||||
|
||||
self._require_touch = QtGui.QCheckBox(m.require_touch)
|
||||
# Touch-required support not available before 4.2.6
|
||||
if self._version >= (4, 2, 6):
|
||||
@ -128,11 +132,26 @@ class AddCredDialog(qt.Dialog):
|
||||
|
||||
def _handle_qr(self, parsed):
|
||||
if parsed:
|
||||
otp_type = parsed['type'].lower()
|
||||
n_digits = parsed.get('digits', '6')
|
||||
algo = parsed.get('algorithm', 'SHA1').upper()
|
||||
|
||||
if otp_type not in ['totp', 'hotp']:
|
||||
QtGui.QMessageBox.warning(self, m.qr_invalid_type, m.qr_invalid_type_desc)
|
||||
return
|
||||
if n_digits not in ['6', '8']:
|
||||
QtGui.QMessageBox.warning(self, m.qr_invalid_digits, m.qr_invalid_digits_desc)
|
||||
return
|
||||
if algo not in ['SHA1', 'SHA256']:
|
||||
# RFC6238 says SHA512 is also supported, but it's not implemented here yet.
|
||||
QtGui.QMessageBox.warning(self, m.qr_invalid_algo, m.qr_invalid_algo_desc)
|
||||
return
|
||||
|
||||
self._cred_name.setText(parsed['name'])
|
||||
self._cred_key.setText(parsed['secret'])
|
||||
n_digits = parsed.get('digits', '6')
|
||||
self._n_digits.setCurrentIndex(0 if n_digits == '6' else 1)
|
||||
if parsed['type'] == 'totp':
|
||||
self._algorithm.setCurrentIndex(0 if algo == 'SHA1' else 1)
|
||||
if otp_type == 'totp':
|
||||
self._cred_totp.setChecked(True)
|
||||
else:
|
||||
self._cred_hotp.setChecked(True)
|
||||
@ -177,6 +196,10 @@ class AddCredDialog(qt.Dialog):
|
||||
def n_digits(self):
|
||||
return int(self._n_digits.currentText())
|
||||
|
||||
@property
|
||||
def algorithm(self):
|
||||
return ALG_SHA1 if self._algorithm.currentIndex() == 0 else ALG_SHA256
|
||||
|
||||
@property
|
||||
def require_touch(self):
|
||||
return self._require_touch.isChecked()
|
||||
|
Loading…
Reference in New Issue
Block a user