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
{
uint8_t friendAddress[TOX_ADDRESS_SIZE] = {0x00};
tox_self_get_address(tox, friendAddress.data());
return ToxId(friendAddress);
tox_self_get_address(tox, friendAddress);
return ToxId(friendAddress, TOX_ADDRESS_SIZE);
}
/**

View File

@ -23,8 +23,8 @@
#include <tox/tox.h>
#include <QRegularExpression>
#include <cstdint>
#include <QRegularExpression>
// Tox doesn't publicly define these
#define NOSPAM_BYTES 4
@ -35,6 +35,8 @@
#define CHECKSUM_HEX_CHARS (2*CHECKSUM_BYTES)
#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
* @brief This class represents a Tox ID.
@ -56,7 +58,7 @@
* @brief The default constructor. Creates an empty Tox ID.
*/
ToxId::ToxId()
: toxId()
: toxId(TOX_ADDRESS_SIZE, 0x00)
{}
/**
@ -103,7 +105,7 @@ ToxId::ToxId(const QString& id)
*/
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
* 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);
checkToxId(tmpId);
constructToxId(tmpId);
}
void ToxId::checkToxId(const QByteArray& rawId)
void ToxId::constructToxId(const QByteArray& rawId)
{
if(rawId.length() == TOX_SECRET_KEY_SIZE)
{
@ -179,18 +181,6 @@ void 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.
* @return The ToxID as uint8_t*
@ -245,27 +235,45 @@ QString ToxId::getNoSpamString() const
* @brief Check, that id is a valid Tox ID.
* @param id Tox ID to check.
* @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)
{
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;
}
uint32_t size = PUBLIC_KEY_HEX_CHARS + NOSPAM_HEX_CHARS;
QString publicKeyStr = id.left(size);
QString checksumStr = id.right(CHECKSUM_HEX_CHARS);
const int size = TOX_PUBLIC_KEY_SIZE + NOSPAM_BYTES;
QByteArray publicKey = QByteArray::fromHex(publicKeyStr.toLatin1());
QByteArray checksum = QByteArray::fromHex(checksumStr.toLatin1());
uint8_t check[2] = {0};
QByteArray data = toxId.left(size);
QByteArray checksum = toxId.right(CHECKSUM_BYTES);
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 caclulated == checksum;
}
return calculated == checksum;
}

View File

@ -30,15 +30,16 @@ public:
ToxId(const ToxId& other);
explicit ToxId(const QString& id);
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;
QString toString() const;
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;
QByteArray getToxId() const;
QByteArray getPublicKey() const;
@ -47,7 +48,10 @@ public:
QString getNoSpamString() const;
private:
void checkToxId(const QByteArray& rawId);
void constructToxId(const QByteArray& rawId);
public:
static const QRegularExpression ToxIdRegEx;
private:
QByteArray toxId;

View File

@ -164,13 +164,13 @@ void AddFriendForm::onSendTriggered()
{
QString id = toxId.text().trimmed();
if (!ToxId::isToxId(id))
if (!ToxId::isValidToxId(id))
{
ToxId toxId = Toxme::lookup(id); // Try Toxme
if (toxId.toString().isEmpty())
{
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;
}
id = toxId.toString();