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:
parent
3d0938a3c6
commit
d196611ffe
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue
Block a user