MTP::AuthKey uses std::array for data.

Also using "volatile char*" iteration for secure memset on Mac/Linux.
This commit is contained in:
John Preston 2017-02-22 18:18:26 +03:00
parent 21efb44e81
commit 90b3b5c3e5
8 changed files with 110 additions and 75 deletions

View File

@ -76,7 +76,6 @@ enum {
LocalEncryptIterCount = 4000, // key derivation iteration count LocalEncryptIterCount = 4000, // key derivation iteration count
LocalEncryptNoPwdIterCount = 4, // key derivation iteration count without pwd (not secure anyway) LocalEncryptNoPwdIterCount = 4, // key derivation iteration count without pwd (not secure anyway)
LocalEncryptSaltSize = 32, // 256 bit LocalEncryptSaltSize = 32, // 256 bit
LocalEncryptKeySize = 256, // 2048 bit
AnimationTimerDelta = 7, AnimationTimerDelta = 7,
ClipThreadsCount = 8, ClipThreadsCount = 8,

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once #pragma once
#include "core/basic_types.h" #include "core/basic_types.h"
#include <array>
namespace base { namespace base {
@ -242,13 +243,37 @@ private:
}; };
int32 hashCrc32(const void *data, uint32 len); int32 hashCrc32(const void *data, uint32 len);
int32 *hashSha1(const void *data, uint32 len, void *dest); // dest - ptr to 20 bytes, returns (int32*)dest int32 *hashSha1(const void *data, uint32 len, void *dest); // dest - ptr to 20 bytes, returns (int32*)dest
inline std::array<char, 20> hashSha1(const void *data, int len) {
auto result = std::array<char, 20>();
hashSha1(data, len, result.data());
return result;
}
int32 *hashSha256(const void *data, uint32 len, void *dest); // dest - ptr to 32 bytes, returns (int32*)dest int32 *hashSha256(const void *data, uint32 len, void *dest); // dest - ptr to 32 bytes, returns (int32*)dest
inline std::array<char, 32> hashSha256(const void *data, int size) {
auto result = std::array<char, 32>();
hashSha1(data, size, result.data());
return result;
}
int32 *hashMd5(const void *data, uint32 len, void *dest); // dest = ptr to 16 bytes, returns (int32*)dest int32 *hashMd5(const void *data, uint32 len, void *dest); // dest = ptr to 16 bytes, returns (int32*)dest
inline std::array<char, 16> hashMd5(const void *data, int size) {
auto result = std::array<char, 16>();
hashMd5(data, size, result.data());
return result;
}
char *hashMd5Hex(const int32 *hashmd5, void *dest); // dest = ptr to 32 bytes, returns (char*)dest char *hashMd5Hex(const int32 *hashmd5, void *dest); // dest = ptr to 32 bytes, returns (char*)dest
inline char *hashMd5Hex(const void *data, uint32 len, void *dest) { // dest = ptr to 32 bytes, returns (char*)dest inline char *hashMd5Hex(const void *data, uint32 len, void *dest) { // dest = ptr to 32 bytes, returns (char*)dest
return hashMd5Hex(HashMd5(data, len).result(), dest); return hashMd5Hex(HashMd5(data, len).result(), dest);
} }
inline std::array<char, 32> hashMd5Hex(const void *data, int size) {
auto result = std::array<char, 32>();
hashMd5Hex(data, size, result.data());
return result;
}
// good random (using openssl implementation) // good random (using openssl implementation)
void memset_rand(void *data, uint32 len); void memset_rand(void *data, uint32 len);

View File

@ -135,9 +135,10 @@ bool _checkStreamStatus(QDataStream &stream) {
QByteArray _settingsSalt, _passKeySalt, _passKeyEncrypted; QByteArray _settingsSalt, _passKeySalt, _passKeyEncrypted;
constexpr auto kLocalKeySize = MTP::AuthKey::kSize;
MTP::AuthKey _oldKey, _settingsKey, _passKey, _localKey; MTP::AuthKey _oldKey, _settingsKey, _passKey, _localKey;
void createLocalKey(const QByteArray &pass, QByteArray *salt, MTP::AuthKey *result) { void createLocalKey(const QByteArray &pass, QByteArray *salt, MTP::AuthKey *result) {
uchar key[LocalEncryptKeySize] = { 0 }; MTP::AuthKey::Data key = { 0 };
int32 iterCount = pass.size() ? LocalEncryptIterCount : LocalEncryptNoPwdIterCount; // dont slow down for no password int32 iterCount = pass.size() ? LocalEncryptIterCount : LocalEncryptNoPwdIterCount; // dont slow down for no password
QByteArray newSalt; QByteArray newSalt;
if (!salt) { if (!salt) {
@ -148,7 +149,7 @@ void createLocalKey(const QByteArray &pass, QByteArray *salt, MTP::AuthKey *resu
cSetLocalSalt(newSalt); cSetLocalSalt(newSalt);
} }
PKCS5_PBKDF2_HMAC_SHA1(pass.constData(), pass.size(), (uchar*)salt->data(), salt->size(), iterCount, LocalEncryptKeySize, key); PKCS5_PBKDF2_HMAC_SHA1(pass.constData(), pass.size(), (uchar*)salt->data(), salt->size(), iterCount, key.size(), (uchar*)key.data());
result->setKey(key); result->setKey(key);
} }
@ -894,18 +895,12 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version) {
case dbiKey: { case dbiKey: {
qint32 dcId; qint32 dcId;
quint32 key[64]; MTP::AuthKey::Data key = { 0 };
stream >> dcId; stream >> dcId;
stream.readRawData((char*)key, 256); stream.readRawData(key.data(), key.size());
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
DEBUG_LOG(("MTP Info: key found, dc %1, key: %2").arg(dcId).arg(Logs::mb(key, 256).str())); MTP::setKey(dcId, key);
dcId = MTP::bareDcId(dcId);
MTP::AuthKeyPtr keyPtr(new MTP::AuthKey());
keyPtr->setKey(key);
keyPtr->setDC(dcId);
MTP::setKey(dcId, keyPtr);
} break; } break;
case dbiAutoStart: { case dbiAutoStart: {
@ -1777,14 +1772,14 @@ void _writeMtpData() {
return; return;
} }
MTP::AuthKeysMap keys = MTP::getKeys(); auto keys = MTP::getKeys();
quint32 size = sizeof(quint32) + sizeof(qint32) + sizeof(quint32); quint32 size = sizeof(quint32) + sizeof(qint32) + sizeof(quint32);
size += keys.size() * (sizeof(quint32) + sizeof(quint32) + 256); size += keys.size() * (sizeof(quint32) + sizeof(quint32) + MTP::AuthKey::kSize);
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
data.stream << quint32(dbiUser) << qint32(MTP::authedId()) << quint32(MTP::maindc()); data.stream << quint32(dbiUser) << qint32(MTP::authedId()) << quint32(MTP::maindc());
for_const (const MTP::AuthKeyPtr &key, keys) { for_const (auto &key, keys) {
data.stream << quint32(dbiKey) << quint32(key->getDC()); data.stream << quint32(dbiKey) << quint32(key->getDC());
key->write(data.stream); key->write(data.stream);
} }
@ -1847,8 +1842,8 @@ ReadMapState _readMap(const QByteArray &pass) {
LOG(("App Info: could not decrypt pass-protected key from map file, maybe bad password...")); LOG(("App Info: could not decrypt pass-protected key from map file, maybe bad password..."));
return ReadMapPassNeeded; return ReadMapPassNeeded;
} }
uchar key[LocalEncryptKeySize] = { 0 }; auto key = MTP::AuthKey::Data { 0 };
if (keyData.stream.readRawData((char*)key, LocalEncryptKeySize) != LocalEncryptKeySize || !keyData.stream.atEnd()) { if (keyData.stream.readRawData(key.data(), key.size()) != key.size() || !keyData.stream.atEnd()) {
LOG(("App Error: could not read pass-protected key from map file")); LOG(("App Error: could not read pass-protected key from map file"));
return ReadMapFailed; return ReadMapFailed;
} }
@ -2044,8 +2039,7 @@ void _writeMap(WriteMapWhen when) {
FileWriteDescriptor map(qsl("map")); FileWriteDescriptor map(qsl("map"));
if (_passKeySalt.isEmpty() || _passKeyEncrypted.isEmpty()) { if (_passKeySalt.isEmpty() || _passKeyEncrypted.isEmpty()) {
uchar local5Key[LocalEncryptKeySize] = { 0 }; QByteArray pass(kLocalKeySize, Qt::Uninitialized), salt(LocalEncryptSaltSize, Qt::Uninitialized);
QByteArray pass(LocalEncryptKeySize, Qt::Uninitialized), salt(LocalEncryptSaltSize, Qt::Uninitialized);
memset_rand(pass.data(), pass.size()); memset_rand(pass.data(), pass.size());
memset_rand(salt.data(), salt.size()); memset_rand(salt.data(), salt.size());
createLocalKey(pass, &salt, &_localKey); createLocalKey(pass, &salt, &_localKey);
@ -2054,7 +2048,7 @@ void _writeMap(WriteMapWhen when) {
memset_rand(_passKeySalt.data(), _passKeySalt.size()); memset_rand(_passKeySalt.data(), _passKeySalt.size());
createLocalKey(QByteArray(), &_passKeySalt, &_passKey); createLocalKey(QByteArray(), &_passKeySalt, &_passKey);
EncryptedDescriptor passKeyData(LocalEncryptKeySize); EncryptedDescriptor passKeyData(kLocalKeySize);
_localKey.write(passKeyData.stream); _localKey.write(passKeyData.stream);
_passKeyEncrypted = FileWriteDescriptor::prepareEncrypted(passKeyData, _passKey); _passKeyEncrypted = FileWriteDescriptor::prepareEncrypted(passKeyData, _passKey);
} }
@ -2376,15 +2370,15 @@ void reset() {
} }
bool checkPasscode(const QByteArray &passcode) { bool checkPasscode(const QByteArray &passcode) {
MTP::AuthKey tmp; auto checkKey = MTP::AuthKey();
createLocalKey(passcode, &_passKeySalt, &tmp); createLocalKey(passcode, &_passKeySalt, &checkKey);
return (tmp == _passKey); return (checkKey == _passKey);
} }
void setPasscode(const QByteArray &passcode) { void setPasscode(const QByteArray &passcode) {
createLocalKey(passcode, &_passKeySalt, &_passKey); createLocalKey(passcode, &_passKeySalt, &_passKey);
EncryptedDescriptor passKeyData(LocalEncryptKeySize); EncryptedDescriptor passKeyData(kLocalKeySize);
_localKey.write(passKeyData.stream); _localKey.write(passKeyData.stream);
_passKeyEncrypted = FileWriteDescriptor::prepareEncrypted(passKeyData, _passKey); _passKeyEncrypted = FileWriteDescriptor::prepareEncrypted(passKeyData, _passKey);

View File

@ -20,30 +20,34 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include <array>
#include <memory>
namespace MTP { namespace MTP {
class AuthKey { class AuthKey {
public: public:
static constexpr auto kSize = 256; // 2048 bits.
AuthKey() : _isset(false), _dc(0) { using Data = std::array<char, kSize>;
}
bool created() const { bool created() const {
return _isset; return _isset;
} }
void setKey(const void *from) { void setKey(const Data &from) {
memcpy(_key, from, 256); _key = from;
uchar sha1Buffer[20]; auto sha1 = hashSha1(_key.data(), _key.size());
_keyId = *(uint64*)(hashSha1(_key, 256, sha1Buffer) + 3);
// Lower 64 bits = 8 bytes of 20 byte SHA1 hash.
_keyId = *reinterpret_cast<uint64*>(sha1.data() + 12);
_isset = true; _isset = true;
} }
void setDC(uint32 dc) { void setDC(int dc) {
_dc = dc; _dc = dc;
} }
uint32 getDC() const { int getDC() const {
t_assert(_isset); t_assert(_isset);
return _dc; return _dc;
} }
@ -60,26 +64,27 @@ public:
uchar data_a[16 + 32], sha1_a[20]; uchar data_a[16 + 32], sha1_a[20];
memcpy(data_a, &msgKey, 16); memcpy(data_a, &msgKey, 16);
memcpy(data_a + 16, _key + x, 32); memcpy(data_a + 16, _key.data() + x, 32);
hashSha1(data_a, 16 + 32, sha1_a); hashSha1(data_a, 16 + 32, sha1_a);
uchar data_b[16 + 16 + 16], sha1_b[20]; uchar data_b[16 + 16 + 16], sha1_b[20];
memcpy(data_b, _key + 32 + x, 16); memcpy(data_b, _key.data() + 32 + x, 16);
memcpy(data_b + 16, &msgKey, 16); memcpy(data_b + 16, &msgKey, 16);
memcpy(data_b + 32, _key + 48 + x, 16); memcpy(data_b + 32, _key.data() + 48 + x, 16);
hashSha1(data_b, 16 + 16 + 16, sha1_b); hashSha1(data_b, 16 + 16 + 16, sha1_b);
uchar data_c[32 + 16], sha1_c[20]; uchar data_c[32 + 16], sha1_c[20];
memcpy(data_c, _key + 64 + x, 32); memcpy(data_c, _key.data() + 64 + x, 32);
memcpy(data_c + 32, &msgKey, 16); memcpy(data_c + 32, &msgKey, 16);
hashSha1(data_c, 32 + 16, sha1_c); hashSha1(data_c, 32 + 16, sha1_c);
uchar data_d[16 + 32], sha1_d[20]; uchar data_d[16 + 32], sha1_d[20];
memcpy(data_d, &msgKey, 16); memcpy(data_d, &msgKey, 16);
memcpy(data_d + 16, _key + 96 + x, 32); memcpy(data_d + 16, _key.data() + 96 + x, 32);
hashSha1(data_d, 16 + 32, sha1_d); hashSha1(data_d, 16 + 32, sha1_d);
uchar *key((uchar*)&aesKey), *iv((uchar*)&aesIV); auto key = reinterpret_cast<uchar*>(&aesKey);
auto iv = reinterpret_cast<uchar*>(&aesIV);
memcpy(key, sha1_a, 8); memcpy(key, sha1_a, 8);
memcpy(key + 8, sha1_b + 8, 12); memcpy(key + 8, sha1_b + 8, 12);
memcpy(key + 8 + 12, sha1_c + 4, 12); memcpy(key + 8 + 12, sha1_c + 4, 12);
@ -91,7 +96,7 @@ public:
void write(QDataStream &to) const { void write(QDataStream &to) const {
t_assert(_isset); t_assert(_isset);
to.writeRawData(_key, 256); to.writeRawData(_key.data(), _key.size());
} }
static const uint64 RecreateKeyId = 0xFFFFFFFFFFFFFFFFL; static const uint64 RecreateKeyId = 0xFFFFFFFFFFFFFFFFL;
@ -99,20 +104,19 @@ public:
friend bool operator==(const AuthKey &a, const AuthKey &b); friend bool operator==(const AuthKey &a, const AuthKey &b);
private: private:
Data _key = { 0 };
char _key[256]; uint64 _keyId = 0;
uint64 _keyId; bool _isset = false;
bool _isset; int _dc = 0;
uint32 _dc;
}; };
inline bool operator==(const AuthKey &a, const AuthKey &b) { inline bool operator==(const AuthKey &a, const AuthKey &b) {
return !memcmp(a._key, b._key, 256); return (a._key == b._key);
} }
typedef QSharedPointer<AuthKey> AuthKeyPtr; using AuthKeyPtr = std::shared_ptr<AuthKey>;
typedef QVector<AuthKeyPtr> AuthKeysMap; using AuthKeysMap = QVector<AuthKeyPtr>;
void aesIgeEncrypt(const void *src, void *dst, uint32 len, const void *key, const void *iv); void aesIgeEncrypt(const void *src, void *dst, uint32 len, const void *key, const void *iv);
void aesIgeDecrypt(const void *src, void *dst, uint32 len, const void *key, const void *iv); void aesIgeDecrypt(const void *src, void *dst, uint32 len, const void *key, const void *iv);

View File

@ -443,7 +443,7 @@ ConnectionPrivate::ConnectionPrivate(QThread *thread, Connection *owner, Session
, _owner(owner) , _owner(owner)
, _waitForReceived(MTPMinReceiveDelay) , _waitForReceived(MTPMinReceiveDelay)
, _waitForConnected(MTPMinConnectDelay) , _waitForConnected(MTPMinConnectDelay)
// , sessionDataMutex(QReadWriteLock::Recursive) //, sessionDataMutex(QReadWriteLock::Recursive)
, sessionData(data) { , sessionData(data) {
oldConnectionTimer.moveToThread(thread); oldConnectionTimer.moveToThread(thread);
_waitForConnectedTimer.moveToThread(thread); _waitForConnectedTimer.moveToThread(thread);
@ -1197,7 +1197,7 @@ void ConnectionPrivate::restart(bool mayBeBadKey) {
_waitForReceivedTimer.stop(); _waitForReceivedTimer.stop();
_waitForConnectedTimer.stop(); _waitForConnectedTimer.stop();
AuthKeyPtr key(sessionData->getKey()); auto key = sessionData->getKey();
if (key) { if (key) {
if (!sessionData->isCheckedKey()) { if (!sessionData->isCheckedKey()) {
if (mayBeBadKey) { if (mayBeBadKey) {
@ -1368,7 +1368,7 @@ void ConnectionPrivate::handleReceived() {
return restart(); return restart();
} }
AuthKeyPtr key(sessionData->getKey()); auto key = sessionData->getKey();
if (!key || key->keyId() != keyId) { if (!key || key->keyId() != keyId) {
DEBUG_LOG(("MTP Error: auth_key id for dc %1 changed").arg(dc)); DEBUG_LOG(("MTP Error: auth_key id for dc %1 changed").arg(dc));
@ -2360,7 +2360,7 @@ void ConnectionPrivate::updateAuthKey() {
keyId = newKeyId; keyId = newKeyId;
return; // some other connection is getting key return; // some other connection is getting key
} }
const AuthKeyPtr &key(sessionData->getKey()); auto key = sessionData->getKey();
newKeyId = key ? key->keyId() : 0; newKeyId = key ? key->keyId() : 0;
} }
if (keyId != newKeyId) { if (keyId != newKeyId) {
@ -2642,15 +2642,14 @@ void ConnectionPrivate::dhClientParamsSend() {
// count g_b and auth_key using openssl BIGNUM methods // count g_b and auth_key using openssl BIGNUM methods
MTP::internal::BigNumCounter bnCounter; MTP::internal::BigNumCounter bnCounter;
if (!bnCounter.count(b, _authKeyStrings->dh_prime.constData(), _authKeyData->g, g_b, _authKeyStrings->g_a.constData(), _authKeyData->auth_key)) { if (!bnCounter.count(b, _authKeyStrings->dh_prime.constData(), _authKeyData->g, g_b, _authKeyStrings->g_a.constData(), _authKeyStrings->auth_key.data())) {
return dhClientParamsSend(); return dhClientParamsSend();
} }
// count auth_key hashes - parts of sha1(auth_key) // count auth_key hashes - parts of sha1(auth_key)
uchar sha1Buffer[20]; auto auth_key_sha = hashSha1(_authKeyStrings->auth_key.data(), _authKeyStrings->auth_key.size());
int32 *auth_key_sha = hashSha1(_authKeyData->auth_key, 256, sha1Buffer); memcpy(&_authKeyData->auth_key_aux_hash, auth_key_sha.data(), 8);
memcpy(&_authKeyData->auth_key_aux_hash, auth_key_sha, 8); memcpy(&_authKeyData->auth_key_hash, auth_key_sha.data() + 12, 8);
memcpy(&_authKeyData->auth_key_hash, auth_key_sha + 3, 8);
MTPSet_client_DH_params req_client_DH_params; MTPSet_client_DH_params req_client_DH_params;
req_client_DH_params.vnonce = _authKeyData->nonce; req_client_DH_params.vnonce = _authKeyData->nonce;
@ -2727,11 +2726,11 @@ void ConnectionPrivate::dhClientParamsAnswered() {
uint64 salt1 = _authKeyData->new_nonce.l.l, salt2 = _authKeyData->server_nonce.l, serverSalt = salt1 ^ salt2; uint64 salt1 = _authKeyData->new_nonce.l.l, salt2 = _authKeyData->server_nonce.l, serverSalt = salt1 ^ salt2;
sessionData->setSalt(serverSalt); sessionData->setSalt(serverSalt);
AuthKeyPtr authKey(new AuthKey()); auto authKey = std::make_shared<AuthKey>();
authKey->setKey(_authKeyData->auth_key); authKey->setKey(_authKeyStrings->auth_key);
authKey->setDC(bareDcId(dc)); authKey->setDC(bareDcId(dc));
DEBUG_LOG(("AuthKey Info: auth key gen succeed, id: %1, server salt: %2, auth key: %3").arg(authKey->keyId()).arg(serverSalt).arg(Logs::mb(_authKeyData->auth_key, 256).str())); DEBUG_LOG(("AuthKey Info: auth key gen succeed, id: %1, server salt: %2").arg(authKey->keyId()).arg(serverSalt));
sessionData->owner()->notifyKeyCreated(authKey); // slot will call authKeyCreated() sessionData->owner()->notifyKeyCreated(authKey); // slot will call authKeyCreated()
sessionData->clear(); sessionData->clear();
@ -2823,17 +2822,28 @@ void ConnectionPrivate::authKeyCreated() {
} }
void ConnectionPrivate::clearAuthKeyData() { void ConnectionPrivate::clearAuthKeyData() {
if (_authKeyData) { auto zeroMemory = [](void *data, int size) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
SecureZeroMemory(_authKeyData.get(), sizeof(AuthKeyCreateData)); SecureZeroMemory(data, size);
if (!_authKeyStrings->dh_prime.isEmpty()) SecureZeroMemory(_authKeyStrings->dh_prime.data(), _authKeyStrings->dh_prime.size()); #else // Q_OS_WIN
if (!_authKeyStrings->g_a.isEmpty()) SecureZeroMemory(_authKeyStrings->g_a.data(), _authKeyStrings->g_a.size()); auto end = static_cast<char*>(data) + size;
#else for (volatile auto p = static_cast<volatile char*>(data); p != end; ++p) {
memset(_authKeyData.get(), 0, sizeof(AuthKeyCreateData)); *p = 0;
if (!_authKeyStrings->dh_prime.isEmpty()) memset(_authKeyStrings->dh_prime.data(), 0, _authKeyStrings->dh_prime.size()); }
if (!_authKeyStrings->g_a.isEmpty()) memset(_authKeyStrings->g_a.data(), 0, _authKeyStrings->g_a.size()); #endif // Q_OS_WIN
#endif };
if (_authKeyData) {
zeroMemory(_authKeyData.get(), sizeof(AuthKeyCreateData));
_authKeyData.reset(); _authKeyData.reset();
}
if (_authKeyStrings) {
if (!_authKeyStrings->dh_prime.isEmpty()) {
zeroMemory(_authKeyStrings->dh_prime.data(), _authKeyStrings->dh_prime.size());
}
if (!_authKeyStrings->g_a.isEmpty()) {
zeroMemory(_authKeyStrings->g_a.data(), _authKeyStrings->g_a.size());
}
zeroMemory(_authKeyStrings->auth_key.data(), _authKeyStrings->auth_key.size());
_authKeyStrings.reset(); _authKeyStrings.reset();
} }
} }
@ -3031,6 +3041,7 @@ void ConnectionPrivate::unlockKey() {
} }
ConnectionPrivate::~ConnectionPrivate() { ConnectionPrivate::~ConnectionPrivate() {
clearAuthKeyData();
t_assert(_finished && _conn == nullptr && _conn4 == nullptr && _conn6 == nullptr); t_assert(_finished && _conn == nullptr && _conn4 == nullptr && _conn6 == nullptr);
} }

View File

@ -77,7 +77,6 @@ class ConnectionPrivate : public QObject {
Q_OBJECT Q_OBJECT
public: public:
ConnectionPrivate(QThread *thread, Connection *owner, SessionData *data, uint32 dc); ConnectionPrivate(QThread *thread, Connection *owner, SessionData *data, uint32 dc);
~ConnectionPrivate(); ~ConnectionPrivate();
@ -89,7 +88,6 @@ public:
QString transport() const; QString transport() const;
signals: signals:
void needToReceive(); void needToReceive();
void needToRestart(); void needToRestart();
void stateChanged(qint32 newState); void stateChanged(qint32 newState);
@ -252,7 +250,6 @@ private:
uchar aesKey[32] = { 0 }; uchar aesKey[32] = { 0 };
uchar aesIV[32] = { 0 }; uchar aesIV[32] = { 0 };
uint32 auth_key[64] = { 0 };
MTPlong auth_key_hash; MTPlong auth_key_hash;
uint32 req_num = 0; // sent not encrypted request number uint32 req_num = 0; // sent not encrypted request number
@ -261,6 +258,7 @@ private:
struct AuthKeyCreateStrings { struct AuthKeyCreateStrings {
QByteArray dh_prime; QByteArray dh_prime;
QByteArray g_a; QByteArray g_a;
AuthKey::Data auth_key = { 0 };
}; };
std::unique_ptr<AuthKeyCreateData> _authKeyData; std::unique_ptr<AuthKeyCreateData> _authKeyData;
std::unique_ptr<AuthKeyCreateStrings> _authKeyStrings; std::unique_ptr<AuthKeyCreateStrings> _authKeyStrings;

View File

@ -895,8 +895,12 @@ AuthKeysMap getKeys() {
return internal::getAuthKeys(); return internal::getAuthKeys();
} }
void setKey(int32 dc, AuthKeyPtr key) { void setKey(int dc, const AuthKey::Data &key) {
return internal::setAuthKey(dc, key); auto dcId = MTP::bareDcId(dc);
auto keyPtr = std::make_shared<MTP::AuthKey>();
keyPtr->setDC(dcId);
keyPtr->setKey(key);
return internal::setAuthKey(dc, std::move(keyPtr));
} }
QReadWriteLock *dcOptionsMutex() { QReadWriteLock *dcOptionsMutex() {

View File

@ -220,7 +220,7 @@ void clearGlobalHandlers();
void updateDcOptions(const QVector<MTPDcOption> &options); void updateDcOptions(const QVector<MTPDcOption> &options);
AuthKeysMap getKeys(); AuthKeysMap getKeys();
void setKey(int32 dc, AuthKeyPtr key); void setKey(int dc, const AuthKey::Data &key);
QReadWriteLock *dcOptionsMutex(); QReadWriteLock *dcOptionsMutex();