mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-12-16 00:44:17 -05:00
Add initial Steam TOTP support
* Add the concept of custom TOTP encoders, each with potential for custom code alphabet, length, step interval and code direction (i.e. reversed) * Select custom encoder via overload of the digits field of a loaded entry * Allow selection of custom encoders via the "TOTP Settings" field's size, as currently done by KeeTrayTOTP for Steam. Use "S" for the short name of the Steam custom encoder * Allow selection of custom encoders via the "otp" field by appending a "&encoder=<name>" field to the URL query. For example, "&encoder=steam" * Update TOTP set-up dialog to permit selection between (default, steam, custom) settings.
This commit is contained in:
parent
1cb91fabb6
commit
8ca52ba8f9
11 changed files with 270 additions and 34 deletions
|
|
@ -83,3 +83,89 @@ void TestTotp::testTotpCode()
|
|||
output = QTotp::generateTotp(seed, time, 8, 30);
|
||||
QCOMPARE(output, QString("69279037"));
|
||||
}
|
||||
|
||||
void TestTotp::testEncoderData()
|
||||
{
|
||||
for (quint8 key: QTotp::encoders.keys()) {
|
||||
const QTotp::Encoder& enc = QTotp::encoders.value(key);
|
||||
QVERIFY2(enc.digits != 0,
|
||||
qPrintable(QString("Custom encoders cannot have zero-value for digits field: %1(%2)")
|
||||
.arg(enc.name)
|
||||
.arg(key)));
|
||||
QVERIFY2(!enc.name.isEmpty(),
|
||||
qPrintable(QString("Custom encoders must have a name: %1(%2)")
|
||||
.arg(enc.name)
|
||||
.arg(key)));
|
||||
QVERIFY2(!enc.shortName.isEmpty(),
|
||||
qPrintable(QString("Custom encoders must have a shortName: %1(%2)")
|
||||
.arg(enc.name)
|
||||
.arg(key)));
|
||||
QVERIFY2(QTotp::shortNameToEncoder.contains(enc.shortName),
|
||||
qPrintable(QString("No shortNameToEncoder entry found for custom encoder: %1(%2) %3")
|
||||
.arg(enc.name)
|
||||
.arg(key)
|
||||
.arg(enc.shortName)));
|
||||
QVERIFY2(QTotp::shortNameToEncoder[enc.shortName] == key,
|
||||
qPrintable(QString("shortNameToEncoder doesn't reference this custome encoder: %1(%2) %3")
|
||||
.arg(enc.name)
|
||||
.arg(key)
|
||||
.arg(enc.shortName)));
|
||||
QVERIFY2(QTotp::nameToEncoder.contains(enc.name),
|
||||
qPrintable(QString("No nameToEncoder entry found for custom encoder: %1(%2) %3")
|
||||
.arg(enc.name)
|
||||
.arg(key)
|
||||
.arg(enc.shortName)));
|
||||
QVERIFY2(QTotp::nameToEncoder[enc.name] == key,
|
||||
qPrintable(QString("nameToEncoder doesn't reference this custome encoder: %1(%2) %3")
|
||||
.arg(enc.name)
|
||||
.arg(key)
|
||||
.arg(enc.shortName)));
|
||||
}
|
||||
|
||||
for (const QString & key: QTotp::nameToEncoder.keys()) {
|
||||
quint8 value = QTotp::nameToEncoder.value(key);
|
||||
QVERIFY2(QTotp::encoders.contains(value),
|
||||
qPrintable(QString("No custom encoder found for encoder named %1(%2)")
|
||||
.arg(value)
|
||||
.arg(key)));
|
||||
QVERIFY2(QTotp::encoders[value].name == key,
|
||||
qPrintable(QString("nameToEncoder doesn't reference the right custom encoder: %1(%2)")
|
||||
.arg(value)
|
||||
.arg(key)));
|
||||
}
|
||||
|
||||
for (const QString & key: QTotp::shortNameToEncoder.keys()) {
|
||||
quint8 value = QTotp::shortNameToEncoder.value(key);
|
||||
QVERIFY2(QTotp::encoders.contains(value),
|
||||
qPrintable(QString("No custom encoder found for short-name encoder %1(%2)")
|
||||
.arg(value)
|
||||
.arg(key)));
|
||||
QVERIFY2(QTotp::encoders[value].shortName == key,
|
||||
qPrintable(QString("shortNameToEncoder doesn't reference the right custom encoder: %1(%2)")
|
||||
.arg(value)
|
||||
.arg(key)));
|
||||
}
|
||||
}
|
||||
|
||||
void TestTotp::testSteamTotp()
|
||||
{
|
||||
quint8 digits = 0;
|
||||
quint8 step = 0;
|
||||
QString secret = "otpauth://totp/"
|
||||
"test:test@example.com?secret=63BEDWCQZKTQWPESARIERL5DTTQFCJTK&issuer=Valve&algorithm="
|
||||
"SHA1&digits=5&period=30&encoder=steam";
|
||||
QCOMPARE(QTotp::parseOtpString(secret, digits, step), QString("63BEDWCQZKTQWPESARIERL5DTTQFCJTK"));
|
||||
QCOMPARE(digits, quint8(QTotp::ENCODER_STEAM));
|
||||
QCOMPARE(step, quint8(30));
|
||||
|
||||
|
||||
QByteArray seed = QString("63BEDWCQZKTQWPESARIERL5DTTQFCJTK").toLatin1();
|
||||
|
||||
// These time/value pairs were created by running the Steam Guard function of the
|
||||
// Steam mobile app with a throw-away steam account. The above secret was extracted
|
||||
// from the Steam app's data for use in testing here.
|
||||
quint64 time = 1511200518;
|
||||
QCOMPARE(QTotp::generateTotp(seed, time, QTotp::ENCODER_STEAM, 30), QString("FR8RV"));
|
||||
time = 1511200714;
|
||||
QCOMPARE(QTotp::generateTotp(seed, time, QTotp::ENCODER_STEAM, 30), QString("9P3VP"));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue