mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-09-01 15:05:56 +00:00
Re-encrypt secure secret with password change.
This commit is contained in:
@@ -12,9 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "passport/passport_encryption.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
PasscodeBox::PasscodeBox(QWidget*, bool turningOff)
|
||||
: _turningOff(turningOff)
|
||||
@@ -27,11 +28,19 @@ PasscodeBox::PasscodeBox(QWidget*, bool turningOff)
|
||||
, _recover(this, lang(lng_signin_recover)) {
|
||||
}
|
||||
|
||||
PasscodeBox::PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff)
|
||||
PasscodeBox::PasscodeBox(
|
||||
QWidget*,
|
||||
const QByteArray &newSalt,
|
||||
const QByteArray &curSalt,
|
||||
bool hasRecovery,
|
||||
const QString &hint,
|
||||
const QByteArray &newSecureSecretSalt,
|
||||
bool turningOff)
|
||||
: _turningOff(turningOff)
|
||||
, _cloudPwd(true)
|
||||
, _newSalt(newSalt)
|
||||
, _curSalt(curSalt)
|
||||
, _newSecureSecretSalt(newSecureSecretSalt)
|
||||
, _hasRecovery(hasRecovery)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_enter_old))
|
||||
@@ -186,7 +195,7 @@ void PasscodeBox::setInnerFocus() {
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::setPasswordDone(const MTPBool &result) {
|
||||
void PasscodeBox::setPasswordDone() {
|
||||
_setRequest = 0;
|
||||
emit reloadPassword();
|
||||
auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated));
|
||||
@@ -312,43 +321,12 @@ void PasscodeBox::save(bool force) {
|
||||
_replacedBy = getDelegate()->show(Box<ConfirmBox>(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, base::lambda_guarded(this, [this] {
|
||||
save(true);
|
||||
})));
|
||||
} else if (_newPasscode->isHidden()) {
|
||||
clearCloudPassword(old);
|
||||
} else if (_oldPasscode->isHidden()) {
|
||||
setNewCloudPassword(pwd);
|
||||
} else {
|
||||
QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt);
|
||||
QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
|
||||
if (pwd.isEmpty()) {
|
||||
hint = QString();
|
||||
email = QString();
|
||||
} else {
|
||||
hashSha256(newPasswordData.constData(), newPasswordData.size(), newPasswordHash.data());
|
||||
}
|
||||
QByteArray oldPasswordData = _oldPasscode->isHidden() ? QByteArray() : (_curSalt + old.toUtf8() + _curSalt);
|
||||
QByteArray oldPasswordHash = _oldPasscode->isHidden() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
|
||||
if (!_oldPasscode->isHidden()) {
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
}
|
||||
auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_password_hash
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
if (_oldPasscode->isHidden() || _newPasscode->isHidden()) {
|
||||
flags |= MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
}
|
||||
const auto newSecureSecret = bytes::vector();
|
||||
const auto newSecureSalt = bytes::vector();
|
||||
const auto newSecureSecretHash = 0ULL;
|
||||
_setRequest = MTP::send(
|
||||
MTPaccount_UpdatePasswordSettings(
|
||||
MTP_bytes(oldPasswordHash),
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
MTP_bytes(_newSalt),
|
||||
MTP_bytes(newPasswordHash),
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
MTP_bytes(newSecureSalt),
|
||||
MTP_bytes(newSecureSecret),
|
||||
MTP_long(newSecureSecretHash))),
|
||||
rpcDone(&PasscodeBox::setPasswordDone),
|
||||
rpcFail(&PasscodeBox::setPasswordFail));
|
||||
changeCloudPassword(old, pwd);
|
||||
}
|
||||
} else {
|
||||
cSetPasscodeBadTries(0);
|
||||
@@ -358,6 +336,225 @@ void PasscodeBox::save(bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::clearCloudPassword(const QString &oldPassword) {
|
||||
Expects(!_oldPasscode->isHidden());
|
||||
|
||||
const auto passwordUtf = oldPassword.toUtf8();
|
||||
const auto oldPasswordData = (_curSalt + passwordUtf + _curSalt);
|
||||
auto oldPasswordHash = QByteArray(32, Qt::Uninitialized);
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
_setRequest = request(MTPaccount_GetPasswordSettings(
|
||||
MTP_bytes(oldPasswordHash)
|
||||
)).done([=](const MTPaccount_PasswordSettings &result) {
|
||||
_setRequest = 0;
|
||||
|
||||
Expects(result.type() == mtpc_account_passwordSettings);
|
||||
const auto &data = result.c_account_passwordSettings();
|
||||
|
||||
if (data.vsecure_secret.v.isEmpty()) {
|
||||
sendClearCloudPassword(oldPasswordHash);
|
||||
return;
|
||||
}
|
||||
warnPassportLoss(oldPasswordHash);
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::sendClearCloudPassword(
|
||||
const QByteArray &oldPasswordHash) {
|
||||
const auto newPasswordData = QByteArray();
|
||||
const auto newPasswordHash = QByteArray();
|
||||
const auto hint = QString();
|
||||
const auto email = QString();
|
||||
const auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_password_hash
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_hint
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
_setRequest = request(MTPaccount_UpdatePasswordSettings(
|
||||
MTP_bytes(oldPasswordHash),
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
MTP_bytes(_newSalt),
|
||||
MTP_bytes(newPasswordHash),
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
MTPbytes(), // new_secure_salt
|
||||
MTPbytes(), // new_secure_secret
|
||||
MTPlong()) // new_secure_secret_id
|
||||
)).done([=](const MTPBool &result) {
|
||||
setPasswordDone();
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::warnPassportLoss(const QByteArray &oldPasswordHash) {
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto sendAndClose = [=] {
|
||||
sendClearCloudPassword(oldPasswordHash);
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
};
|
||||
*box = getDelegate()->show(Box<ConfirmBox>(
|
||||
lang(lng_cloud_password_passport_losing),
|
||||
lang(lng_continue),
|
||||
sendAndClose));
|
||||
}
|
||||
|
||||
void PasscodeBox::setNewCloudPassword(const QString &newPassword) {
|
||||
const auto newPasswordData = (_newSalt + newPassword.toUtf8() + _newSalt);
|
||||
auto newPasswordHash = QByteArray(32, Qt::Uninitialized);
|
||||
hashSha256(newPasswordData.constData(), newPasswordData.size(), newPasswordHash.data());
|
||||
const auto oldPasswordData = QByteArray();
|
||||
const auto oldPasswordHash = QByteArray();
|
||||
const auto hint = _passwordHint->getLastText();
|
||||
const auto email = _recoverEmail->getLastText().trimmed();
|
||||
const auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_password_hash
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_hint
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
_setRequest = request(MTPaccount_UpdatePasswordSettings(
|
||||
MTP_bytes(oldPasswordHash),
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
MTP_bytes(_newSalt),
|
||||
MTP_bytes(newPasswordHash),
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
MTPbytes(), // new_secure_salt
|
||||
MTPbytes(), // new_secure_secret
|
||||
MTPlong()) // new_secure_secret_id
|
||||
)).done([=](const MTPBool &result) {
|
||||
setPasswordDone();
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::changeCloudPassword(
|
||||
const QString &oldPassword,
|
||||
const QString &newPassword) {
|
||||
const auto passwordUtf = oldPassword.toUtf8();
|
||||
const auto oldPasswordData = (_curSalt + passwordUtf + _curSalt);
|
||||
auto oldPasswordHash = QByteArray(32, Qt::Uninitialized);
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
_setRequest = request(MTPaccount_GetPasswordSettings(
|
||||
MTP_bytes(oldPasswordHash)
|
||||
)).done([=](const MTPaccount_PasswordSettings &result) {
|
||||
_setRequest = 0;
|
||||
|
||||
Expects(result.type() == mtpc_account_passwordSettings);
|
||||
const auto &data = result.c_account_passwordSettings();
|
||||
|
||||
if (data.vsecure_secret.v.isEmpty()) {
|
||||
const auto empty = QByteArray();
|
||||
sendChangeCloudPassword(oldPasswordHash, newPassword, empty);
|
||||
return;
|
||||
}
|
||||
const auto secret = Passport::DecryptSecureSecret(
|
||||
bytes::make_span(data.vsecure_salt.v),
|
||||
bytes::make_span(data.vsecure_secret.v),
|
||||
bytes::make_span(passwordUtf));
|
||||
if (secret.empty()) {
|
||||
LOG(("API Error: Failed to decrypt secure secret."));
|
||||
suggestSecretReset(oldPasswordHash, newPassword);
|
||||
} else if (Passport::CountSecureSecretId(secret) != data.vsecure_secret_id.v) {
|
||||
LOG(("API Error: Wrong secure secret id."));
|
||||
suggestSecretReset(oldPasswordHash, newPassword);
|
||||
} else {
|
||||
sendChangeCloudPassword(
|
||||
oldPasswordHash,
|
||||
newPassword,
|
||||
QByteArray::fromRawData(
|
||||
reinterpret_cast<const char*>(secret.data()),
|
||||
secret.size()));
|
||||
}
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::suggestSecretReset(
|
||||
const QByteArray &oldPasswordHash,
|
||||
const QString &newPassword) {
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto resetSecretAndSave = [=] {
|
||||
using Flag = MTPDaccount_passwordInputSettings::Flag;
|
||||
_setRequest = request(MTPaccount_UpdatePasswordSettings(
|
||||
MTP_bytes(oldPasswordHash),
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(Flag::f_new_secure_salt
|
||||
| Flag::f_new_secure_secret
|
||||
| Flag::f_new_secure_secret_id),
|
||||
MTPbytes(), // new_salt
|
||||
MTPbytes(), // new_password_hash
|
||||
MTPstring(), // hint
|
||||
MTPstring(), // email
|
||||
MTP_bytes(QByteArray()), // new_secure_salt
|
||||
MTP_bytes(QByteArray()), // new_secure_secret
|
||||
MTP_long(0)) // new_secure_secret_id
|
||||
)).done([=](const MTPBool &result) {
|
||||
_setRequest = 0;
|
||||
const auto empty = QByteArray();
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
sendChangeCloudPassword(oldPasswordHash, newPassword, empty);
|
||||
}).fail([=](const RPCError &error) {
|
||||
_setRequest = 0;
|
||||
}).send();
|
||||
};
|
||||
*box = getDelegate()->show(Box<ConfirmBox>(
|
||||
Lang::Hard::PassportCorrupted(),
|
||||
Lang::Hard::PassportCorruptedReset(),
|
||||
[=] { resetSecretAndSave(); }));
|
||||
}
|
||||
|
||||
void PasscodeBox::sendChangeCloudPassword(
|
||||
const QByteArray &oldPasswordHash,
|
||||
const QString &newPassword,
|
||||
const QByteArray &secureSecret) {
|
||||
const auto passwordUtf = newPassword.toUtf8();
|
||||
const auto newPasswordData = (_newSalt + passwordUtf + _newSalt);
|
||||
auto newPasswordHash = QByteArray(32, Qt::Uninitialized);
|
||||
hashSha256(newPasswordData.constData(), newPasswordData.size(), newPasswordHash.data());
|
||||
const auto hint = _passwordHint->getLastText();
|
||||
auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_password_hash
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
auto newSecureSecret = bytes::vector();
|
||||
auto newSecureSecretId = 0ULL;
|
||||
if (!secureSecret.isEmpty()) {
|
||||
flags |= MTPDaccount_passwordInputSettings::Flag::f_new_secure_salt
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_secure_secret
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_secure_secret_id;
|
||||
newSecureSecretId = Passport::CountSecureSecretId(
|
||||
bytes::make_span(secureSecret));
|
||||
newSecureSecret = Passport::EncryptSecureSecret(
|
||||
bytes::make_span(_newSecureSecretSalt),
|
||||
bytes::make_span(secureSecret),
|
||||
bytes::make_span(passwordUtf));
|
||||
}
|
||||
_setRequest = request(MTPaccount_UpdatePasswordSettings(
|
||||
MTP_bytes(oldPasswordHash),
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
MTP_bytes(_newSalt),
|
||||
MTP_bytes(newPasswordHash),
|
||||
MTP_string(hint),
|
||||
MTPstring(), // email is not changing
|
||||
MTP_bytes(_newSecureSecretSalt),
|
||||
MTP_bytes(newSecureSecret),
|
||||
MTP_long(newSecureSecretId))
|
||||
)).done([=](const MTPBool &result) {
|
||||
setPasswordDone();
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::badOldPasscode() {
|
||||
_oldPasscode->selectAll();
|
||||
_oldPasscode->setFocus();
|
||||
@@ -396,7 +593,12 @@ void PasscodeBox::emailChanged() {
|
||||
void PasscodeBox::recoverByEmail() {
|
||||
if (_pattern.isEmpty()) {
|
||||
_pattern = "-";
|
||||
MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PasscodeBox::recoverStarted), rpcFail(&PasscodeBox::recoverStartFail));
|
||||
request(MTPauth_RequestPasswordRecovery(
|
||||
)).done([=](const MTPauth_PasswordRecovery &result) {
|
||||
recoverStarted(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
recoverStartFail(error);
|
||||
}).send();
|
||||
} else {
|
||||
recover();
|
||||
}
|
||||
|
Reference in New Issue
Block a user