diff options
author | Janek Bevendorff <janek@jbev.net> | 2018-02-28 00:38:05 +0300 |
---|---|---|
committer | Janek Bevendorff <janek@jbev.net> | 2018-02-28 00:38:05 +0300 |
commit | 4c0ed74341173482415c484a2ad07df204150213 (patch) | |
tree | 74ebd72444c8e9db43698383151ddca6d7fb4506 /src/totp/totp.cpp | |
parent | 4723f66d23db95f8318f04ee3aeae448d2305c9c (diff) | |
parent | 1db064425a22d997a2b6740c73a7b0cb1310fe07 (diff) |
Release 2.3.02.3.0
- Add support for KDBX 4.0, Argon2 and ChaCha20 [#148, #1179, #1230, #1494]
- Add SSH Agent feature [#1098, #1450, #1463]
- Add preview panel with details of the selected entry [#879, #1338]
- Add more and configurable columns to entry table and allow copying of values by double click [#1305]
- Add KeePassXC-Browser API as a replacement for KeePassHTTP [#608]
- Deprecate KeePassHTTP [#1392]
- Add support for Steam one-time passwords [#1206]
- Add support for multiple Auto-Type sequences for a single entry [#1390]
- Adjust YubiKey HMAC-SHA1 challenge-response key generation for KDBX 4.0 [#1060]
- Replace qHttp with cURL for website icon downloads [#1460]
- Remove lock file [#1231]
- Add option to create backup file before saving [#1385]
- Ask to save a generated password before closing the entry password generator [#1499]
- Resolve placeholders recursively [#1078]
- Add Auto-Type button to the toolbar [#1056]
- Improve window focus handling for Auto-Type dialogs [#1204, #1490]
- Auto-Type dialog and password generator can now be exited with ESC [#1252, #1412]
- Add optional dark tray icon [#1154]
- Add new "Unsafe saving" option to work around saving problems with file sync services [#1385]
- Add IBus support to AppImage and additional image formats to Windows builds [#1534, #1537]
- Add diceware password generator to CLI [#1406]
- Add --key-file option to CLI [#816, #824]
- Add DBus interface for opening and closing KeePassXC databases [#283]
- Add KDBX compression options to database settings [#1419]
- Discourage use of old fixed-length key files in favor of arbitrary files [#1326, #1327]
- Correct reference resolution in entry fields [#1486]
- Fix window state and recent databases not being remembered on exit [#1453]
- Correct history item generation when configuring TOTP for an entry [#1446]
- Correct multiple TOTP bugs [#1414]
- Automatic saving after every change is now a default [#279]
- Allow creation of new entries during search [#1398]
- Correct menu issues on macOS [#1335]
- Allow compilation on OpenBSD [#1328]
- Improve entry attachments view [#1139, #1298]
- Fix auto lock for Gnome and Xfce [#910, #1249]
- Don't remember key files in file dialogs when the setting is disabled [#1188]
- Improve database merging and conflict resolution [#807, #1165]
- Fix macOS pasteboard issues [#1202]
- Improve startup times on some platforms [#1205]
- Hide the notes field by default [#1124]
- Toggle main window by clicking tray icon with the middle mouse button [#992]
- Fix custom icons not copied over when databases are merged [#1008]
- Allow use of DEL key to delete entries [#914]
- Correct intermittent crash due to stale history items [#1527]
- Sanitize newline characters in title, username and URL fields [#1502]
- Reopen previously opened databases in correct order [#774]
- Use system's zxcvbn library if available [#701]
- Implement various i18n improvements [#690, #875, #1436]
Diffstat (limited to 'src/totp/totp.cpp')
-rw-r--r-- | src/totp/totp.cpp | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index 7a584def2..f102335aa 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -28,14 +28,47 @@ #include <QtEndian> #include <cmath> -const quint8 QTotp::defaultStep = 30; -const quint8 QTotp::defaultDigits = 6; +const quint8 Totp::defaultStep = 30; +const quint8 Totp::defaultDigits = 6; -QTotp::QTotp() +/** + * Custom encoder types. Each should be unique and >= 128 and < 255 + * Values have no meaning outside of keepassxc + */ +/** + * Encoder for Steam Guard TOTP + */ +const quint8 Totp::ENCODER_STEAM = 254; + +const Totp::Encoder Totp::defaultEncoder = { "", "", "0123456789", 0, 0, false }; +const QMap<quint8, Totp::Encoder> Totp::encoders{ + { Totp::ENCODER_STEAM, { "steam", "S", "23456789BCDFGHJKMNPQRTVWXY", 5, 30, true } }, +}; + +/** + * These map the second field of the "TOTP Settings" field to our internal encoder number + * that overloads the digits field. Make sure that the key matches the shortName value + * in the corresponding Encoder + * NOTE: when updating this map, a corresponding edit to the settings regex must be made + * in Entry::totpSeed() + */ +const QMap<QString, quint8> Totp::shortNameToEncoder{ + { "S", Totp::ENCODER_STEAM }, +}; +/** + * These map the "encoder=" URL parameter of the "otp" field to our internal encoder number + * that overloads the digits field. Make sure that the key matches the name value + * in the corresponding Encoder + */ +const QMap<QString, quint8> Totp::nameToEncoder{ + { "steam", Totp::ENCODER_STEAM }, +}; + +Totp::Totp() { } -QString QTotp::parseOtpString(QString key, quint8& digits, quint8& step) +QString Totp::parseOtpString(QString key, quint8& digits, quint8& step) { QUrl url(key); @@ -57,7 +90,10 @@ QString QTotp::parseOtpString(QString key, quint8& digits, quint8& step) if (q_step > 0 && q_step <= 60) { step = q_step; } - + QString encName = query.queryItemValue("encoder"); + if (!encName.isEmpty() && nameToEncoder.contains(encName)) { + digits = nameToEncoder[encName]; + } } else { // Compatibility with "KeeOtp" plugin string format QRegExp rx("key=(.+)", Qt::CaseInsensitive, QRegExp::RegExp); @@ -92,7 +128,7 @@ QString QTotp::parseOtpString(QString key, quint8& digits, quint8& step) return seed; } -QString QTotp::generateTotp(const QByteArray key, +QString Totp::generateTotp(const QByteArray key, quint64 time, const quint8 numDigits = defaultDigits, const quint8 step = defaultStep) @@ -119,20 +155,34 @@ QString QTotp::generateTotp(const QByteArray key, | (hmac[offset + 3] & 0xff); // clang-format on - quint32 digitsPower = pow(10, numDigits); + const Encoder& encoder = encoders.value(numDigits, defaultEncoder); + // if encoder.digits is 0, we need to use the passed-in number of digits (default encoder) + quint8 digits = encoder.digits == 0 ? numDigits : encoder.digits; + int direction = -1; + int startpos = digits - 1; + if (encoder.reverse) { + direction = 1; + startpos = 0; + } + quint32 digitsPower = pow(encoder.alphabet.size(), digits); quint64 password = binary % digitsPower; - return QString("%1").arg(password, numDigits, 10, QChar('0')); + QString retval(int(digits), encoder.alphabet[0]); + for (quint8 pos = startpos; password > 0; pos += direction) { + retval[pos] = encoder.alphabet[int(password % encoder.alphabet.size())]; + password /= encoder.alphabet.size(); + } + return retval; } // See: https://github.com/google/google-authenticator/wiki/Key-Uri-Format -QUrl QTotp::generateOtpString(const QString& secret, +QUrl Totp::generateOtpString(const QString& secret, const QString& type, const QString& issuer, const QString& username, const QString& algorithm, - const quint8& digits, - const quint8& step) + quint8 digits, + quint8 step) { QUrl keyUri; keyUri.setScheme("otpauth"); |