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

Merge branch 'toxme'

This commit is contained in:
tux3 2015-02-25 00:41:20 +01:00
commit 8e10eedca7
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
5 changed files with 191 additions and 0 deletions

View File

@ -1107,6 +1107,19 @@ QString Core::getIDString() const
// 16^n > 10^10 (which is roughly the planet's population) // 16^n > 10^10 (which is roughly the planet's population)
} }
QPair<QByteArray, QByteArray> Core::getKeypair() const
{
QPair<QByteArray, QByteArray> keypair;
if (!tox)
return keypair;
char buf[2*TOX_PUBLIC_KEY_SIZE];
tox_get_keys(tox, (uint8_t*)buf, (uint8_t*)buf+TOX_PUBLIC_KEY_SIZE);
keypair.first = QByteArray(buf, TOX_PUBLIC_KEY_SIZE);
keypair.second = QByteArray(buf+TOX_PUBLIC_KEY_SIZE, TOX_PUBLIC_KEY_SIZE);
return keypair;
}
QString Core::getStatusMessage() const QString Core::getStatusMessage() const
{ {
QString sname; QString sname;

View File

@ -72,6 +72,7 @@ public:
QString getUsername() const; ///< Returns our username, or an empty string on failure QString getUsername() const; ///< Returns our username, or an empty string on failure
QString getStatusMessage() const; ///< Returns our status message, or an empty string on failure QString getStatusMessage() const; ///< Returns our status message, or an empty string on failure
ToxID getSelfId() const; ///< Returns our Tox ID ToxID getSelfId() const; ///< Returns our Tox ID
QPair<QByteArray, QByteArray> getKeypair() const; ///< Returns our public and private keys
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source

View File

@ -32,6 +32,8 @@
#include <sodium.h> #include <sodium.h>
#include "toxme.h"
#ifdef LOG_TO_FILE #ifdef LOG_TO_FILE
static QtMessageHandler dflt; static QtMessageHandler dflt;
static QTextStream* logFile {nullptr}; static QTextStream* logFile {nullptr};

137
src/toxme.cpp Normal file
View File

@ -0,0 +1,137 @@
#include "toxme.h"
#include "core.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QCoreApplication>
#include <sodium/crypto_box.h>
#include <sodium/randombytes.h>
#include <string>
const QString Toxme::apiUrl{"https://toxme.se/api"};
const unsigned char Toxme::pinnedPk[] = {0x5D, 0x72, 0xC5, 0x17, 0xDF, 0x6A, 0xEC, 0x54, 0xF1, 0xE9, 0x77, 0xA6, 0xB6, 0xF2, 0x59, 0x14,
0xEA, 0x4C, 0xF7, 0x27, 0x7A, 0x85, 0x02, 0x7C, 0xD9, 0xF5, 0x19, 0x6D, 0xF1, 0x7E, 0x0B, 0x13};
QByteArray Toxme::makeJsonRequest(QString json)
{
QNetworkAccessManager netman;
QNetworkRequest request{apiUrl};
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply* reply = netman.post(request,json.toUtf8());
while (!reply->isFinished())
qApp->processEvents();
return reply->readAll();
}
QByteArray Toxme::prepareEncryptedJson(int action, QString payload)
{
QPair<QByteArray, QByteArray> keypair = Core::getInstance()->getKeypair();
if (keypair.first.isEmpty() || keypair.second.isEmpty())
{
qWarning() << "Toxme::prepareEncryptedJson: Couldn't get our keypair, aborting";
return QByteArray();
}
QByteArray nonce(crypto_box_NONCEBYTES, 0);
randombytes((uint8_t*)nonce.data(), crypto_box_NONCEBYTES);
QByteArray payloadData = payload.toUtf8();
const size_t cypherlen = crypto_box_MACBYTES+payloadData.size();
unsigned char* payloadEnc = new unsigned char[cypherlen];
crypto_box_easy(payloadEnc,(uint8_t*)payloadData.data(),payloadData.size(),
(uint8_t*)nonce.data(),pinnedPk,(uint8_t*)keypair.second.data());
QByteArray payloadEncData(reinterpret_cast<char*>(payloadEnc), cypherlen);
delete[] payloadEnc;
const QString json{"{\"action\":"+QString().setNum(action)+","
"\"public_key\":\""+keypair.first.toHex()+"\","
"\"encrypted\":\""+payloadEncData.toBase64()+"\","
"\"nonce\":\""+nonce.toBase64()+"\"}"};
return json.toUtf8();
}
ToxID Toxme::lookup(QString address)
{
// JSON injection ?
address.replace('\\',"\\\\");
address.replace('"',"\"");
ToxID id;
const QString json{"{\"action\":3,\"name\":\""+address+"\"}"};
static const QByteArray pattern{"public_key\""};
QByteArray response = makeJsonRequest(json);
const int index = response.indexOf(pattern);
if (index == -1)
return id;
response = response.mid(index+pattern.size());
const int idStart = response.indexOf('"');
if (idStart == -1)
return id;
response = response.mid(idStart+1);
const int idEnd = response.indexOf('"');
if (idEnd == -1)
return id;
response.truncate(idEnd);
id = ToxID::fromString(response);
return id;
}
int Toxme::extractError(QString json)
{
static const QByteArray pattern{"c\":"};
json = json.remove(' ');
const int index = json.indexOf(pattern);
if (index == -1)
return INT_MIN;
json = json.mid(index+pattern.size());
const int end = json.indexOf('}');
if (end == -1)
return INT_MIN;
json.truncate(end);
bool ok;
int r = json.toInt(&ok);
if (!ok)
return INT_MIN;
return r;
}
bool Toxme::createAddress(ToxID id, QString address,
bool keepPrivate, QString bio)
{
int privacy = keepPrivate ? 0 : 2;
// JSON injection ?
bio.replace('\\',"\\\\");
bio.replace('"',"\"");
address.replace('\\',"\\\\");
address.replace('"',"\"");
const QString payload{"{\"tox_id\":\""+id.toString()+"\","
"\"name\":\""+address+"\","
"\"privacy\":"+QString().setNum(privacy)+","
"\"bio\":\""+bio+"\","
"\"timestamp\":"+QString().setNum(time(0))+"}"};
QByteArray response = makeJsonRequest(prepareEncryptedJson(1,payload));
return (extractError(response) == 0);
}
bool Toxme::deleteAddress(ToxID id)
{
const QString payload{"{\"public_key\":\""+id.toString().left(64)+"\","
"\"timestamp\":"+QString().setNum(time(0))+"}"};
QByteArray response = makeJsonRequest(prepareEncryptedJson(2,payload));
return (extractError(response) == 0);
}

38
src/toxme.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef TOXME_H
#define TOXME_H
#include <QString>
#include <QMutex>
#include <memory>
#include "corestructs.h"
class QNetworkAccessManager;
/// This class implements a client for the toxme.se API
/// The class is thread safe
/// May process events while waiting for blocking calls
class Toxme
{
public:
/// Converts a toxme.se address to a Tox ID, returns an empty ID on error
static ToxID lookup(QString address);
/// Creates a new toxme.se address associated with a Tox ID.
/// If keepPrivate, the address will not be published on toxme.se
/// The bio is a short optional description of yourself if you want to publish your address.
static bool createAddress(ToxID id, QString address,
bool keepPrivate=true, QString bio=QString());
/// Deletes the address associated with your current Tox ID
static bool deleteAddress(ToxID id);
private:
Toxme()=delete;
static QByteArray makeJsonRequest(QString json);
static QByteArray prepareEncryptedJson(int action, QString payload);
static int extractError(QString json);
private:
static const QString apiUrl;
static const unsigned char pinnedPk[];
};
#endif // TOXME_H