One downside of offloading the token computation to a worker thread and having to do token decryption is an increase in latency.
For the case with a few accounts this latency does not matter, but in case of many accounts it can induce a significant delay when refreshing tokens in the UI.
To hide this latency, when computing an OTP token for the current state of the account the logical 'next' token is also computed as well and cached in the Account object.
When the next (re)computation of the OTP token is requested, the cached 'next' value is reused if still valid before the next pair of tokens is being computed.
This way the apparent latency of a token update is reduced to an near immediate property update in the UI, hiding the actual latency of the computation itself.
This 'optimisation' is implemented in the dumbest possible fashion that can still work.
This means that the code complexity of the change is quite limited, at the cost of rougly doubling the actual work being performed in the worker thread.
Previously a user could accidentally trigger an additional 'add account' action even when the action (button) was not visible in the UI.
This oversight is now fixed.
- Introduce re-usable account name + issuer form. This will help to support overriding account name/issuer when adding accounts via OTP token URI/QR code
- Move common settings out of TokenDetailsForm into AddAccount.qml
Issues: #7
This change prepares the UI for supporting alternative and more complex flows for adding accounts.
All parameters are now collated into a single "validated input" object which is more convenient to pass around between views
This makes it possible to support back- and forth navigation between "basic" and "advanced/details" forms for adding accounts.
Additionally it provides a fundamental building block for adding alternative ways to add accounts (e.g. via OTP token URI/QR code).
Issues: #7
With this the AccountStorage module now fully supports some HOTP/TOTP parameters which are uncommon (but still part of HOTP/TOTP specifications).
- Better types for offset, tokenLength. Make this consistent throughout
- Finish support for offset, checksum parameters for HOTP tokens in AccountStorage
- Finish support for hashing algorithm, epoch parameters for TOTP tokens in AccountStorage
- Better API for creating oath::Algorithm instances
- Code formatting (break up long lines)
Issues: #7
With this change account storage and model work with accounts for which an issuer is recorded.
This is a prerequisite for fully supporting otpauth:// URIs (necessary for QR code support) in Keysmith.
Issues: #7, #13
See-Also: https://github.com/google/google-authenticator/wiki/Key-Uri-Format
- Increase height
- Make the left edge sit flush with the edge of the list item
- Fix colour contrast when a list item is being highlighted (pressed/checked)
Turns out that SwipeListItem (and derivatives) absolutely must have an `id` value of `listItem`.
With this change the account list entries now display a proper flood fill effect when pressed on Android.
In some cases Keysmith may be suspended and animations/timers are no longer updated.
With this change, the application now detects when it is being 'woken' from suspend and refreshes the UI.
- Refactor code to have delegates per account-type & simplify code
- Rework layouting in terms of anchors
- Fix positioning of account name and token labels to be vertically
centered
- Make health indicator/token life timer for TOTP accounts sit flush
with the bottom of the TOTP delegate UI itself and extend along the
whole width. This resolves issue #11
Two bits of boolean state are introduces to track whether or not:
- an error has occurred
- accounts have been loaded from storage yet
This change paves the way for having error handling UX.
With this change token secrets are encrypted prior to writing them to
storage, and decrypted as and when needed to generate tokens. Additional
validation is performed to verify that token secrets can be decrypted
successfully when loading accounts from storage.
With this change issue #6 should finally be resolved.
With this change Keysmith now prompts the user to either:
- setup a new password
- supply an existing password (if detected)
Additionally the organisation/structure of the QML is cleaned up a bit.
All QML pages are dedicated QML files and a few signals are introduced
to provide slightly better encapsulation/decouple interdependencies.
With this change an unlock stage is introduced to loading account storage.
Key derivation parameters for a master key are recorded, and the master
password may be supplied to "unlock" the account secret(s) in storage.
This change paves the way for actually decrypting encrypted account
secrets later, and finally solving issue #6.
Introduce a secrets library which implements the necessary crypto using
libsodium. This change provides the basic building blocks for resolving
issue #6.
Delegate recycling causes a bug when removing an account and then adding
it back: the old, stale UI for the account is reused instead of a new one.
In combination with 'alive' guard property on the UI for account entries,
this results in the account entry becoming frozen in the old stale state.
(Incorrect helath indicators, tokens that do not update and buttons that no
longer respond anymore.)
After triggering the removal of an account from storage in the UI, it may
be possible for the UI not to fully reflect this change for a while yet.
During this short time window, it is possible for an operation to occur on
an already deleted account object which is a use-after-free bug.
In particular signals from animations and timers in the QML UI might still
trigger which causes a slot to be invoked that accesses the underlying
account object.
This change introduces a guard property called 'alive' which is flipped
when the account removal operation is triggered. Slots are updated to
check for the alive status of the UI before proceeding with other logic.
With this change the "Add" button in the "Add account" page is not enabled
until the entered account name and details are valid. Additionally, the UI
for entering the token secret now uses a password field with appropriate
hints for input methods.
This change fixes input validation for the following cases:
- Check that entered account names are still available
- Working validation for time steps (input mask was completely broken)
- Allow longer tokens: liboath is no longer used, Keysmith can handle it
Additionally the QML code is refactored significantly:
- Extracted the main accounts overview page
- Extracted the add an account page
- Completed the internal renaming of "Oath" to "Keysmith" for QML types
This change is a workaround for behaviour of QML controls: when fixup is
called during input validation, the `acceptableInput` property is not
updated correctly.
Provide a building block towards re-implementing the HOTP/TOTP
algorithms without using oath-toolkit: see issue #9.
The hmac::compute function trades simplicity (having to pre-allocate
a scratch buffer) for avoding accidental leaks of key material
(security).
This particular trade-off will help with resolving issue #6.
Provide a custom base32 implementation; relates to issues: #9 and #6.
In particular being able to control memory allocation prior to
decoding base32 will help with resolving issue #6 in a (more) secure
fashion.
* do cmake_minimum_required as first thing, as recommended
* bump KF to 5.37, first release with Kirigami (Qt 5.7 matching min dep)
* use KF5_MIN_VERSION also with ECM
* include KDE CMake settings as first
* remove unused cmake includes
* remove duplicated enable_testing()
* use correct KDEInstallDirs variables
The account details page has a kind of modality:
- hide mode: in which the user is shown the account info but sensitive information such as secret keys should not be displayed openly visible.
- show mode: the same, but in this case all details are openly visible. This will be useful for showing QR codes explicitly.
- edit mode: in which the user may edit account details (all except the name).
- Add a new static library "validator_lib" covering the "validators" namespace in C++
- Introduce the Base32Validator to perform input field validation with fixup support
Due to our use of liboath for generating the actual tokens, we also support only a limited range of valid token lengths.
This means that it is more user friendly to express those limits directly in the UI through a SpinBox instead of allowing the user type in values we do not currently support.