1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

feat(toxid): Improve validation of Tox IDs

This commit is contained in:
sudden6 2016-12-28 15:43:11 +01:00
parent 3d0938a3c6
commit d196611ffe
No known key found for this signature in database
GPG Key ID: 279509B499E032B9
4 changed files with 50 additions and 38 deletions

View File

@ -859,8 +859,8 @@ void Core::setAvatar(const QByteArray& data)
ToxId Core::getSelfId() const ToxId Core::getSelfId() const
{ {
uint8_t friendAddress[TOX_ADDRESS_SIZE] = {0x00}; uint8_t friendAddress[TOX_ADDRESS_SIZE] = {0x00};
tox_self_get_address(tox, friendAddress.data()); tox_self_get_address(tox, friendAddress);
return ToxId(friendAddress); return ToxId(friendAddress, TOX_ADDRESS_SIZE);
} }
/** /**

View File

@ -23,8 +23,8 @@
#include <tox/tox.h> #include <tox/tox.h>
#include <QRegularExpression>
#include <cstdint> #include <cstdint>
#include <QRegularExpression>
// Tox doesn't publicly define these // Tox doesn't publicly define these
#define NOSPAM_BYTES 4 #define NOSPAM_BYTES 4
@ -35,6 +35,8 @@
#define CHECKSUM_HEX_CHARS (2*CHECKSUM_BYTES) #define CHECKSUM_HEX_CHARS (2*CHECKSUM_BYTES)
#define TOXID_HEX_CHARS (2*TOX_ADDRESS_SIZE) #define TOXID_HEX_CHARS (2*TOX_ADDRESS_SIZE)
const QRegularExpression ToxId::ToxIdRegEx = QRegularExpression(QString("(^|\\s)[A-Fa-f0-9]{%1}($|\\s)").arg(TOXID_HEX_CHARS));
/** /**
* @class ToxId * @class ToxId
* @brief This class represents a Tox ID. * @brief This class represents a Tox ID.
@ -56,7 +58,7 @@
* @brief The default constructor. Creates an empty Tox ID. * @brief The default constructor. Creates an empty Tox ID.
*/ */
ToxId::ToxId() ToxId::ToxId()
: toxId() : toxId(TOX_ADDRESS_SIZE, 0x00)
{} {}
/** /**
@ -103,7 +105,7 @@ ToxId::ToxId(const QString& id)
*/ */
ToxId::ToxId(const QByteArray& rawId) ToxId::ToxId(const QByteArray& rawId)
{ {
checkToxId(rawId); constructToxId(rawId);
} }
/** /**
@ -117,14 +119,14 @@ ToxId::ToxId(const QByteArray& rawId)
* @param len Number of bytes to read. Must be TOX_SECRET_KEY_SIZE for a Public Key or * @param len Number of bytes to read. Must be TOX_SECRET_KEY_SIZE for a Public Key or
* TOX_ADDRESS_SIZE for a Tox ID. * TOX_ADDRESS_SIZE for a Tox ID.
*/ */
ToxId::ToxId(const uint8_t& rawId, int len) ToxId::ToxId(const uint8_t* rawId, int len)
{ {
QByteArray tmpId(reinterpret_cast<const char *>(rawId), len); QByteArray tmpId(reinterpret_cast<const char *>(rawId), len);
checkToxId(tmpId); constructToxId(tmpId);
} }
void ToxId::checkToxId(const QByteArray& rawId) void ToxId::constructToxId(const QByteArray& rawId)
{ {
if(rawId.length() == TOX_SECRET_KEY_SIZE) if(rawId.length() == TOX_SECRET_KEY_SIZE)
{ {
@ -179,18 +181,6 @@ void ToxId::clear()
toxId.clear(); toxId.clear();
} }
/**
* @brief Check, that id is probably a valid Tox ID.
* @param id Tox ID to check.
* @return True if the string can be a ToxID, false otherwise.
* @note Doesn't validate checksum.
*/
bool ToxId::isValidToxId(const QString& id)
{
const QRegularExpression hexRegExp("^[A-Fa-f0-9]+$");
return id.length() == TOXID_HEX_CHARS && id.contains(hexRegExp);
}
/** /**
* @brief Gets the ToxID as bytes, convenience function for toxcore interface. * @brief Gets the ToxID as bytes, convenience function for toxcore interface.
* @return The ToxID as uint8_t* * @return The ToxID as uint8_t*
@ -245,27 +235,45 @@ QString ToxId::getNoSpamString() const
* @brief Check, that id is a valid Tox ID. * @brief Check, that id is a valid Tox ID.
* @param id Tox ID to check. * @param id Tox ID to check.
* @return True if id is a valid Tox ID, false otherwise. * @return True if id is a valid Tox ID, false otherwise.
* @note Validates the checksum.
*/
bool ToxId::isValidToxId(const QString& id)
{
return isToxId(id) && ToxId(id).isValid();
}
/**
* @brief Check, that id is probably a valid Tox ID.
* @param id Tox ID to check.
* @return True if the string can be a ToxID, false otherwise.
* @note Doesn't validate checksum.
*/ */
bool ToxId::isToxId(const QString& id) bool ToxId::isToxId(const QString& id)
{ {
if (!isValidToxId(id)) return id.length() == TOXID_HEX_CHARS && id.contains(ToxIdRegEx);
}
/**
* @brief Check it it's a valid Tox ID by verifying the checksum
* @return True if it is a valid Tox ID, false otherwise.
*/
bool ToxId::isValid() const
{
if(toxId.length() != TOX_ADDRESS_SIZE)
{ {
return false; return false;
} }
uint32_t size = PUBLIC_KEY_HEX_CHARS + NOSPAM_HEX_CHARS; const int size = TOX_PUBLIC_KEY_SIZE + NOSPAM_BYTES;
QString publicKeyStr = id.left(size);
QString checksumStr = id.right(CHECKSUM_HEX_CHARS);
QByteArray publicKey = QByteArray::fromHex(publicKeyStr.toLatin1()); QByteArray data = toxId.left(size);
QByteArray checksum = QByteArray::fromHex(checksumStr.toLatin1()); QByteArray checksum = toxId.right(CHECKSUM_BYTES);
uint8_t check[2] = {0}; QByteArray calculated(CHECKSUM_BYTES, 0x00);
for (uint32_t i = 0; i < size / 2; i++) for (int i = 0; i < size; i++)
{ {
check[i % 2] ^= publicKey.data()[i]; calculated[i % 2] = calculated[i % 2] ^ data[i];
} }
QByteArray caclulated(reinterpret_cast<char*>(check), 2); return calculated == checksum;
return caclulated == checksum; }
}

View File

@ -30,15 +30,16 @@ public:
ToxId(const ToxId& other); ToxId(const ToxId& other);
explicit ToxId(const QString& id); explicit ToxId(const QString& id);
explicit ToxId(const QByteArray& rawId); explicit ToxId(const QByteArray& rawId);
explicit ToxId(const uint8_t& rawId, int len); explicit ToxId(const uint8_t* rawId, int len);
bool operator==(const ToxId& other) const; bool operator==(const ToxId& other) const;
bool operator!=(const ToxId& other) const; bool operator!=(const ToxId& other) const;
QString toString() const; QString toString() const;
void clear(); void clear();
bool isValid() const;
static bool isToxId(const QString& id); static bool isValidToxId(const QString& id);
static bool isValidToxId(const QString &id); static bool isToxId(const QString &id);
const uint8_t* getBytes() const; const uint8_t* getBytes() const;
QByteArray getToxId() const; QByteArray getToxId() const;
QByteArray getPublicKey() const; QByteArray getPublicKey() const;
@ -47,7 +48,10 @@ public:
QString getNoSpamString() const; QString getNoSpamString() const;
private: private:
void checkToxId(const QByteArray& rawId); void constructToxId(const QByteArray& rawId);
public:
static const QRegularExpression ToxIdRegEx;
private: private:
QByteArray toxId; QByteArray toxId;

View File

@ -164,13 +164,13 @@ void AddFriendForm::onSendTriggered()
{ {
QString id = toxId.text().trimmed(); QString id = toxId.text().trimmed();
if (!ToxId::isToxId(id)) if (!ToxId::isValidToxId(id))
{ {
ToxId toxId = Toxme::lookup(id); // Try Toxme ToxId toxId = Toxme::lookup(id); // Try Toxme
if (toxId.toString().isEmpty()) if (toxId.toString().isEmpty())
{ {
GUI::showWarning(tr("Couldn't add friend"), GUI::showWarning(tr("Couldn't add friend"),
tr("This Tox ID does not exist", "Toxme error")); tr("This Tox ID is invalid or does not exist", "Toxme error"));
return; return;
} }
id = toxId.toString(); id = toxId.toString();