From 970f2c7fad0121634fbb6266630f187e8403e075 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Oct 2014 15:15:16 -0700 Subject: [PATCH] have DSAI generate a username signature upon request, when it has private key --- libraries/networking/src/AccountManager.h | 2 +- .../networking/src/DataServerAccountInfo.cpp | 51 ++++++++++++++++++- .../networking/src/DataServerAccountInfo.h | 5 +- libraries/networking/src/NodeList.cpp | 7 +-- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 9c111c8d7b..7b5ea8de8b 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -70,7 +70,7 @@ public: void requestAccessToken(const QString& login, const QString& password); void requestProfile(); - const DataServerAccountInfo& getAccountInfo() const { return _accountInfo; } + DataServerAccountInfo& getAccountInfo() { return _accountInfo; } public slots: void requestAccessTokenFinished(); diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index e6c800a1a7..27860c32d7 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include "DataServerAccountInfo.h" @@ -21,7 +23,8 @@ DataServerAccountInfo::DataServerAccountInfo() : _walletID(), _balance(0), _hasBalance(false), - _privateKey() + _privateKey(), + _usernameSignature() { } @@ -64,6 +67,9 @@ void DataServerAccountInfo::setUsername(const QString& username) { if (_username != username) { _username = username; + // clear our username signature so it has to be re-created + _usernameSignature = QByteArray(); + qDebug() << "Username changed to" << username; } } @@ -114,6 +120,49 @@ void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject setWalletID(QUuid(user["wallet_id"].toString())); } +const QByteArray& DataServerAccountInfo::usernameSignature() { + if (_usernameSignature.isEmpty()) { + if (!_privateKey.isEmpty()) { + const char* privateKeyData = _privateKey.constData(); + RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL, + reinterpret_cast(&privateKeyData), + _privateKey.size()); + if (rsaPrivateKey) { + QByteArray usernameByteArray = _username.toUtf8(); + QByteArray encryptedUsername(RSA_size(rsaPrivateKey), 0); + + int encryptReturn = RSA_private_encrypt(usernameByteArray.size(), + reinterpret_cast(usernameByteArray.constData()), + reinterpret_cast(encryptedUsername.data()), + rsaPrivateKey, RSA_PKCS1_PADDING); + + if (encryptReturn != -1) { + _usernameSignature = usernameByteArray; + _usernameSignature.append(encryptedUsername); + } else { + qDebug() << "Error encrypting username signature."; + qDebug() << "Will re-attempt on next domain-server check in."; + } + } else { + qDebug() << "Could not create RSA struct from QByteArray private key."; + qDebug() << "Will re-attempt on next domain-server check in."; + } + } else { + qDebug() << "No private key present in DataServerAccountInfo. Re-log to generate new key."; + qDebug() << "Returning empty username signature."; + } + } + + return _usernameSignature; +} + +void DataServerAccountInfo::setPrivateKey(const QByteArray& privateKey) { + _privateKey = privateKey; + + // clear our username signature so it has to be re-created + _usernameSignature = QByteArray(); +} + QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) { out << info._accessToken << info._username << info._xmppPassword << info._discourseApiKey << info._walletID << info._privateKey; diff --git a/libraries/networking/src/DataServerAccountInfo.h b/libraries/networking/src/DataServerAccountInfo.h index 14419b929c..2a569ada14 100644 --- a/libraries/networking/src/DataServerAccountInfo.h +++ b/libraries/networking/src/DataServerAccountInfo.h @@ -42,8 +42,8 @@ public: const QUuid& getWalletID() const { return _walletID; } void setWalletID(const QUuid& walletID); - const QByteArray& getPrivateKey() const { return _privateKey; } - void setPrivateKey(const QByteArray& privateKey) { _privateKey = privateKey; } + const QByteArray& usernameSignature(); + void setPrivateKey(const QByteArray& privateKey); qint64 getBalance() const { return _balance; } float getBalanceInSatoshis() const { return _balance / SATOSHIS_PER_CREDIT; } @@ -71,6 +71,7 @@ private: qint64 _balance; bool _hasBalance; QByteArray _privateKey; + QByteArray _usernameSignature; }; #endif // hifi_DataServerAccountInfo_h diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index b6983e17e3..1cfe9c21f3 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -310,11 +310,12 @@ void NodeList::sendDomainServerCheckIn() { } // if this is a connect request, and we can present a username signature, send it along - AccountManager& accountManager = AccountManager::getInstance(); - const QByteArray& privateKey = accountManager.getAccountInfo().getPrivateKey(); if (!_domainHandler.isConnected()) { - if (!privateKey.isEmpty()) { + const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().usernameSignature(); + + if (!usernameSignature.isEmpty()) { qDebug() << "Including username signature in domain connect request."; + packetStream << usernameSignature; } else { qDebug() << "Private key not present - domain connect request cannot include username signature"; }