-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
df361e8
commit 8a19281
Showing
5 changed files
with
73 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2017 KeePassXC Team <[email protected]> | ||
* Copyright (C) 2024 KeePassXC Team <[email protected]> | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
|
@@ -24,7 +24,6 @@ | |
#include "Base32.h" | ||
|
||
#include <QHash> | ||
#include <QVariant> | ||
|
||
constexpr quint64 MASK_40BIT = quint64(0xF8) << 32; | ||
constexpr quint64 MASK_35BIT = quint64(0x7C0000000); | ||
|
@@ -43,10 +42,10 @@ constexpr quint8 ASCII_a = static_cast<quint8>('a'); | |
constexpr quint8 ASCII_z = static_cast<quint8>('z'); | ||
constexpr quint8 ASCII_EQ = static_cast<quint8>('='); | ||
|
||
QVariant Base32::decode(const QByteArray& encodedData) | ||
QByteArray Base32::decode(const QByteArray& encodedData) | ||
{ | ||
if (encodedData.size() <= 0) { | ||
return QVariant::fromValue(QByteArray("")); | ||
return {}; | ||
} | ||
|
||
if (encodedData.size() % 8 != 0) { | ||
|
@@ -139,7 +138,7 @@ QVariant Base32::decode(const QByteArray& encodedData) | |
Q_ASSERT(encodedData.size() == i); | ||
Q_ASSERT(nBytes == o); | ||
|
||
return QVariant::fromValue(data); | ||
return data; | ||
} | ||
|
||
QByteArray Base32::encode(const QByteArray& data) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2017 KeePassXC Team <[email protected]> | ||
* Copyright (C) 2024 KeePassXC Team <[email protected]> | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
|
@@ -25,13 +25,12 @@ | |
#define BASE32_H | ||
|
||
#include <QByteArray> | ||
#include <QVariant> | ||
|
||
class Base32 | ||
{ | ||
public: | ||
Base32() = default; | ||
Q_REQUIRED_RESULT static QVariant decode(const QByteArray&); | ||
Q_REQUIRED_RESULT static QByteArray decode(const QByteArray&); | ||
Q_REQUIRED_RESULT static QByteArray encode(const QByteArray&); | ||
Q_REQUIRED_RESULT static QByteArray addPadding(const QByteArray&); | ||
Q_REQUIRED_RESULT static QByteArray removePadding(const QByteArray&); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
/* | ||
* Copyright (C) 2024 KeePassXC Team <[email protected]> | ||
* Copyright (C) 2017 Weslly Honorato <[email protected]> | ||
* Copyright (C) 2017 KeePassXC Team <[email protected]> | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
|
@@ -200,8 +200,8 @@ QString Totp::generateTotp(const QSharedPointer<Totp::Settings>& settings, const | |
current = qToBigEndian(time / step); | ||
} | ||
|
||
QVariant secret = Base32::decode(Base32::sanitizeInput(settings->key.toLatin1())); | ||
if (secret.isNull()) { | ||
const auto secret = Base32::decode(Base32::sanitizeInput(settings->key.toLatin1())); | ||
if (secret.isEmpty()) { | ||
return QObject::tr("Invalid Key", "TOTP"); | ||
} | ||
|
||
|
@@ -218,7 +218,7 @@ QString Totp::generateTotp(const QSharedPointer<Totp::Settings>& settings, const | |
break; | ||
} | ||
QMessageAuthenticationCode code(cryptoHash); | ||
code.setKey(secret.toByteArray()); | ||
code.setKey(secret); | ||
code.addData(QByteArray(reinterpret_cast<char*>(¤t), sizeof(current))); | ||
QByteArray hmac = code.result(); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2017 KeePassXC Team <[email protected]> | ||
* Copyright (C) 2024 KeePassXC Team <[email protected]> | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
|
@@ -26,134 +26,134 @@ void TestBase32::testDecode() | |
{ | ||
// 3 quanta, all upper case + padding | ||
QByteArray encodedData = "JBSWY3DPEB3W64TMMQXC4LQ="; | ||
QVariant data = Base32::decode(encodedData); | ||
QByteArray data = Base32::decode(encodedData); | ||
QString expectedData = "Hello world..."; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// 4 quanta, all upper case | ||
encodedData = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "12345678901234567890"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// 4 quanta, all lower case | ||
encodedData = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "12345678901234567890"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// 4 quanta, mixed upper and lower case | ||
encodedData = "Gezdgnbvgy3tQojqgezdGnbvgy3tQojQ"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "12345678901234567890"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// 1 pad characters | ||
encodedData = "ORSXG5A="; | ||
data = Base32::decode(encodedData); | ||
expectedData = "test"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// 3 pad characters | ||
encodedData = "L5PV6==="; | ||
data = Base32::decode(encodedData); | ||
expectedData = "___"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// 4 pad characters | ||
encodedData = "MZXW6IDCMFZA===="; | ||
data = Base32::decode(encodedData); | ||
expectedData = "foo bar"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// six pad characters | ||
encodedData = "MZXW6YTBOI======"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "foobar"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "IA======"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "@"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
// error: illegal character | ||
encodedData = "1MZXW6YTBOI====="; | ||
data = Base32::decode(encodedData); | ||
QVERIFY(data.isNull()); | ||
QVERIFY(data.isEmpty()); | ||
|
||
// error: missing pad character | ||
encodedData = "MZXW6YTBOI====="; | ||
data = Base32::decode(encodedData); | ||
QVERIFY(data.isNull()); | ||
QVERIFY(data.isEmpty()); | ||
|
||
// RFC 4648 test vectors | ||
encodedData = ""; | ||
data = Base32::decode(encodedData); | ||
expectedData = ""; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "MY======"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "f"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "MZXQ===="; | ||
data = Base32::decode(encodedData); | ||
expectedData = "fo"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "MZXW6==="; | ||
data = Base32::decode(encodedData); | ||
QVERIFY(!data.isNull()); | ||
QVERIFY(!data.isEmpty()); | ||
expectedData = "foo"; | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "MZXW6YQ="; | ||
data = Base32::decode(encodedData); | ||
expectedData = "foob"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "MZXW6YTB"; | ||
expectedData = "fooba"; | ||
data = Base32::decode(encodedData); | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
|
||
encodedData = "MZXW6YTBOI======"; | ||
data = Base32::decode(encodedData); | ||
expectedData = "foobar"; | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), expectedData); | ||
QVERIFY(data.value<QByteArray>().size() == expectedData.size()); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), expectedData); | ||
QVERIFY(data.size() == expectedData.size()); | ||
} | ||
|
||
void TestBase32::testEncode() | ||
|
@@ -307,25 +307,25 @@ void TestBase32::testSanitizeInput() | |
// sanitize input (white space + missing padding) | ||
QByteArray encodedData = "JBSW Y3DP EB3W 64TM MQXC 4LQA"; | ||
auto data = Base32::decode(Base32::sanitizeInput(encodedData)); | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), QString("Hello world...")); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), QString("Hello world...")); | ||
|
||
// sanitize input (typo + missing padding) | ||
encodedData = "J8SWY3DPE83W64TMMQXC4LQA"; | ||
data = Base32::decode(Base32::sanitizeInput(encodedData)); | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), QString("Hello world...")); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), QString("Hello world...")); | ||
|
||
// sanitize input (other illegal characters) | ||
encodedData = "J8SWY3D[PE83W64TMMQ]XC!4LQA"; | ||
data = Base32::decode(Base32::sanitizeInput(encodedData)); | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), QString("Hello world...")); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), QString("Hello world...")); | ||
|
||
// sanitize input (NUL character) | ||
encodedData = "J8SWY3DPE83W64TMMQXC4LQA"; | ||
encodedData.insert(3, '\0'); | ||
data = Base32::decode(Base32::sanitizeInput(encodedData)); | ||
QVERIFY(!data.isNull()); | ||
QCOMPARE(data.toString(), QString("Hello world...")); | ||
QVERIFY(!data.isEmpty()); | ||
QCOMPARE(QString(data.toStdString().c_str()), QString("Hello world...")); | ||
} |