Merge branch 'master' into totp-improvements
This commit is contained in:
@@ -68,6 +68,9 @@ Please see the [How to use Keepass2Android with YubiKey NEO](How-to-use-Keepass2
|
||||
## Advanced usage of the Keepass2Android keyboard
|
||||
Please see the [Advanced usage of the Keepass2Android keyboard](Advanced-usage-of-the-Keepass2Android-keyboard.md) page.
|
||||
|
||||
## Using Keepass2Android like an authenticator app to generate Time-based One-Time-Passwords (TOTPs)
|
||||
Please see [Generating TOTPs with Keepass2Android](Generating-TOTPs.md)
|
||||
|
||||
# FAQ
|
||||
|
||||
## Should I use the KP2A keyboard for entering passwords?
|
||||
|
53
docs/Generating-TOTPs.md
Normal file
53
docs/Generating-TOTPs.md
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
## TOTP in brief
|
||||
TOTP stands for [Time-based One-Time Password algorithm](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm) which is one of the most common way proposed by websites to do a [two-factor authentication (2FA)](https://en.wikipedia.org/wiki/Multi-factor_authentication).
|
||||
|
||||
On these websites, this option will often be mentioned in the 2FA configuration menu as things like "_use code generated by an application_", "_use [Google] Authenticator app_".
|
||||
|
||||
You're prompted to scan a QR code with the app, which essentially contains a code called "_seed_", usually with a form like "_AZER TYUI OPQS DFGH JKLM_", used to generate TOTPs. The seed can be also directly copied if there is no scanning option on the app.
|
||||
|
||||
Most common apps:
|
||||
|
||||
- Google Authenticator
|
||||
- Authy
|
||||
- Microsoft Authenticator
|
||||
- FreeOTP
|
||||
- LastPass Authenticator
|
||||
|
||||
## TOTP in KeePass and benefits
|
||||
In KeePass (by Dominik Reichl) there is are several ways to enable this Authenticator app ability:
|
||||
|
||||
- built-in TOTP support: https://keepass.info/help/base/placeholders.html#otp
|
||||
- [KeePassOTP plugin](https://keepass.info/plugins.html#kpotp)
|
||||
- [KeeOtp plugin](https://keepass.info/plugins.html#keeotp)
|
||||
- [KeeTrayTOTP plugin](https://keepass.info/plugins.html#keetraytotp) (note the name "_TrayTOTP_" on this one for later)
|
||||
|
||||
KeePassXC also supports TOTP: https://keepassxc.org/docs/KeePassXC_UserGuide#_adding_totp_to_an_entry
|
||||
|
||||
The greatest benefits are:
|
||||
|
||||
- the seed stays available contrary to the above apps (for which it's more or less hard to backup/restore/switch with another app)
|
||||
- TOTPs are available wherever the KeePass database is available. But conceptually it's not really 2FA anymore (all things are stored in the same place).
|
||||
|
||||
The different implementations use different ways of storing the TOTP seed (or secret, or key) and optional settings (e.g. the length of the TOTP to generate) within an entry inside the kdbx database. Keepass2Android attempts to be able to read the different formats, but can only write one:
|
||||
|
||||
## TOTP in Keepass2Android
|
||||
|
||||
If you use any of the tools mentioned above, you can set up TOTP entries with them. Keepass2Android can read those entries and generate TOTPs if any of the following styles are used:
|
||||
|
||||
* Keepass2 style: used when there are TimeOtp-Secret(-XXX) fields in the entry
|
||||
* KeeOtpPlugin style: used when there is an otp field containing a query string in the form of key=abc&step=X&size=Y (step and size are optional)
|
||||
* KeeWebOtp/Key Uri Format style: used when entry contains a URL starting with otpauth://totp/, e.g. otpauth://totp/?secret=abc (https://github.com/google/google-authenticator/wiki/Key-Uri-Format)
|
||||
* KeeTrayTotp style:
|
||||
* requires a non-empty seed field (default key is "TOTP seed", can be changed in KP2A settings), value is base32 encoded data
|
||||
* requires a non-empty settings field (default key is "TOTP Settings", can be changed as well), value is expected to be a csv-separated array with [Duration];Length(;TimeCorrectionURL). Length is either an integer value or "S" to indicate Steam encoding
|
||||
|
||||
In order to view the generated TOTP code in KP2A, open the corresponding entry. You can then
|
||||
* use a dynamically generated field called "_TOTP_" containing the TOTP or
|
||||
* use the "Copy TOTP" button on the system notification for the selected entry or
|
||||
* switch to the KP2A keyboard and use the TOTP button to insert the TOTP value into the target app or browser
|
||||
|
||||
If you want to configure an entry to contain the TOTP fields, it is suggested to enter edit mode for the entry. Then click the "Configure TOTP" button. You can either enter the data manually or scan a QR code with the information.
|
||||
|
||||
### Spaces in otp field
|
||||
Make sure that the URI doesn't contain spaces, otherwise KeePass2Android will fail to generate TOTPs as a space is an invalid character. If your URIs have spaces, check [this comment](https://github.com/PhilippC/keepass2android/issues/1248#issuecomment-628035961)._
|
@@ -5,6 +5,7 @@ using keepass2android;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Cryptography;
|
||||
using KeePassLib.Utility;
|
||||
using KeeTrayTOTP.Libraries;
|
||||
|
||||
namespace PluginTOTP
|
||||
{
|
||||
@@ -76,7 +77,7 @@ namespace PluginTOTP
|
||||
secretFieldKey = strPrefix + "Secret-Base32";
|
||||
entryFields.TryGetValue(secretFieldKey, out str);
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
return MemUtil.ParseBase32(str);
|
||||
return Base32.Decode(str);
|
||||
|
||||
secretFieldKey = strPrefix + "Secret-Base64";
|
||||
entryFields.TryGetValue(secretFieldKey, out str);
|
||||
|
@@ -31,17 +31,8 @@ namespace PluginTOTP
|
||||
_muteWarnings = muteWarnings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if specified Entry contains Settings that are not null.
|
||||
/// </summary>
|
||||
internal bool SettingsCheck(IDictionary<string, string> entryFields)
|
||||
{
|
||||
string settings;
|
||||
entryFields.TryGetValue(SettingsFieldName, out settings);
|
||||
return !String.IsNullOrEmpty(settings);
|
||||
}
|
||||
|
||||
internal bool SeedCheck(IDictionary<string, string> entryFields)
|
||||
|
||||
internal bool HasSeed(IDictionary<string, string> entryFields)
|
||||
{
|
||||
string seed;
|
||||
entryFields.TryGetValue(SeedFieldName, out seed);
|
||||
@@ -100,15 +91,15 @@ namespace PluginTOTP
|
||||
}
|
||||
|
||||
private string[] SettingsGet(IDictionary<string, string> entryFields)
|
||||
{
|
||||
return entryFields[SettingsFieldName].Split(';');
|
||||
}
|
||||
{
|
||||
return entryFields.TryGetValue(SettingsFieldName, out var settings) ? settings.Split(';') : new[] { "30", "6" };
|
||||
}
|
||||
|
||||
public TotpData GetTotpData(IDictionary<string, string> entryFields)
|
||||
{
|
||||
TotpData res = new TotpData();
|
||||
|
||||
if (SettingsCheck(entryFields) && SeedCheck(entryFields))
|
||||
if (HasSeed(entryFields))
|
||||
{
|
||||
bool ValidInterval; bool ValidLength; bool ValidUrl;
|
||||
if (SettingsValidate(entryFields, out ValidInterval, out ValidLength, out ValidUrl))
|
||||
|
Reference in New Issue
Block a user