Parital fix for padding error using RSA_sign and RSA_verify

This commit is contained in:
bwent 2015-08-05 14:07:25 -07:00
parent 60fdc390c5
commit 8868148c94
4 changed files with 28 additions and 47 deletions

View file

@ -651,14 +651,14 @@ void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet)
// if username is empty, don't attempt to unpack username signature
if(isRestrictingAccess) {
if (!username.isEmpty()) {
qDebug() << "Reading username signature.";
packetStream >> usernameSignature;
if(usernameSignature.isEmpty()) {
// if user didn't include username and usernameSignature in connect request, send a connectionToken packet
QUuid& connectionToken = _connectionTokenHash[username.toLower()];
if(connectionToken.isNull()) {
if (connectionToken.isNull()) {
connectionToken = QUuid::createUuid();
}
@ -667,14 +667,12 @@ void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet)
connectionTokenPacket->write(connectionToken.toRfc4122());
limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr());
qDebug() << "Sending connection token. " << _connectionTokenHash[username.toLower()];
qDebug() << "Sending connectionToken packet with connectionUUID " << _connectionTokenHash[username.toLower()];
return;
}
}
}
QString reason;
@ -820,7 +818,6 @@ bool DomainServer::verifyUserSignature(const QString& username,
QByteArray publicKeyArray = _userPublicKeys.value(username);
QUuid connectionToken = _connectionTokenHash.value(username.toLower());
qDebug() << "Pulling out connection token. " << connectionToken;
if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) {
// if we do have a public key for the user, check for a signature match
@ -830,46 +827,37 @@ bool DomainServer::verifyUserSignature(const QString& username,
// first load up the public key into an RSA struct
RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size());
qDebug() << "Signature: " << usernameSignature.toHex();
//qDebug() << "Verifying signature: " << usernameSignature.toHex();
QByteArray lowercaseUsername = username.toLower().toUtf8();
QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256);
if (rsaPublicKey) {
QByteArray decryptedArray(RSA_size(rsaPublicKey), 0);
int decryptResult =
RSA_public_decrypt(usernameSignature.size(),
reinterpret_cast<const unsigned char*>(usernameSignature.constData()),
reinterpret_cast<unsigned char*>(decryptedArray.data()),
rsaPublicKey, RSA_PKCS1_PADDING);
RSA_verify(NID_sha256, reinterpret_cast<const unsigned char*>(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast<const unsigned char*>(usernameSignature.constData()), usernameSignature.size(), rsaPublicKey);
QByteArray lowercaseUsername = username.toLower().toUtf8();
QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256);
int err = ERR_get_error();
qDebug() << "Error: " << err;
qDebug() << "Decrypt result: " << decryptResult << " Error: " << err;
if (decryptResult != -1) {
if (usernameWithToken == decryptedArray) {
qDebug() << "Username signature matches for" << username << "- allowing connection.";
if (decryptResult == 1) {
qDebug() << "Username signature matches for" << username << "- allowing connection.";
// free up the public key before we return
RSA_free(rsaPublicKey);
// free up the public key before we return
RSA_free(rsaPublicKey);
// remove the username's connection token from the hash
_connectionTokenHash.remove(username);
// remove the username's connection token from the hash
_connectionTokenHash.remove(username);
return true;
} else {
qDebug() << "Username signature did not match for" << username << "- denying connection.";
reasonReturn = "Username signature did not match.";
}
return true;
} else {
qDebug() << "Couldn't decrypt user signature for" << username << "- denying connection.";
reasonReturn = "Couldn't decrypt user signature.";
qDebug() << "Error decrypting username signature for " << username << "- denying connection.";
reasonReturn = "Error decrypting username signature.";
// free up the public key, we don't need it anymore
RSA_free(rsaPublicKey);
}
// free up the public key, we don't need it anymore
RSA_free(rsaPublicKey);
} else {
// we can't let this user in since we couldn't convert their public key to an RSA key we could use

View file

@ -10,6 +10,7 @@
//
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <qjsondocument.h>
#include <QtCore/QDebug>
@ -30,8 +31,7 @@ DataServerAccountInfo::DataServerAccountInfo() :
_walletID(),
_balance(0),
_hasBalance(false),
_privateKey(),
_usernameSignature()
_privateKey()
{
}
@ -73,9 +73,6 @@ void DataServerAccountInfo::setAccessTokenFromJSON(const QJsonObject& jsonObject
void DataServerAccountInfo::setUsername(const QString& username) {
if (_username != username) {
_username = username;
// clear our username signature so it has to be re-created
_usernameSignature = QByteArray();
qCDebug(networking) << "Username changed to" << username;
}
@ -138,13 +135,10 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo
if (rsaPrivateKey) {
QByteArray lowercaseUsername = _username.toLower().toUtf8();
QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256);
QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0);
int encryptReturn = RSA_private_encrypt(usernameWithToken.size(),
reinterpret_cast<const unsigned char*>(usernameWithToken.constData()),
reinterpret_cast<unsigned char*>(usernameSignature.data()),
rsaPrivateKey, RSA_PKCS1_PADDING);
QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0);
unsigned int usernameSignatureSize = 0;
int encryptReturn = RSA_sign(NID_sha256, reinterpret_cast<const unsigned char*>(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast<unsigned char*>(usernameSignature.data()), &usernameSignatureSize, rsaPrivateKey);
// free the private key RSA struct now that we are done with it
RSA_free(rsaPrivateKey);
@ -154,7 +148,6 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo
qCDebug(networking) << "Will re-attempt on next domain-server check in.";
} else {
qDebug(networking) << "Signing username with connectionUUID " << connectionToken;
qDebug() << "Signature: " << usernameSignature.toHex();
return usernameSignature;
}
@ -169,8 +162,6 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo
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) {

View file

@ -73,7 +73,7 @@ private:
qint64 _balance;
bool _hasBalance;
QByteArray _privateKey;
QByteArray _usernameSignature;
};
#endif // hifi_DataServerAccountInfo_h

View file

@ -289,6 +289,7 @@ void NodeList::sendDomainServerCheckIn() {
QByteArray usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken);
if (!usernameSignature.isEmpty()) {
qDebug() << "Sending signature to packet stream " << usernameSignature.toHex();
packetStream << usernameSignature;
}
}
@ -463,6 +464,7 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer<NLPacket>
// refuse to process this packet if we aren't currently connected to the DS
return;
}
qDebug() << "Setting connection token and sending domain server checkin";
// read in the connection token from the packet, then send domain-server checkin
_domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID)));
sendDomainServerCheckIn();