Update layer to 84.
GitOrigin-RevId: a2057596f00201ee967e7d038e048b618f6e629d
This commit is contained in:
parent
6c1408565e
commit
00fabb8f97
@ -468,7 +468,7 @@ authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string s
|
|||||||
|
|
||||||
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
|
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
|
||||||
|
|
||||||
account.password#68873ba5 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes = account.Password;
|
account.password#ad2641f8 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes = account.Password;
|
||||||
|
|
||||||
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
|
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
|
||||||
|
|
||||||
@ -900,7 +900,7 @@ savedPhoneContact#1142bd56 phone:string first_name:string last_name:string date:
|
|||||||
account.takeout#4dba4501 id:long = account.Takeout;
|
account.takeout#4dba4501 id:long = account.Takeout;
|
||||||
|
|
||||||
passwordKdfAlgoUnknown#d45ab096 = PasswordKdfAlgo;
|
passwordKdfAlgoUnknown#d45ab096 = PasswordKdfAlgo;
|
||||||
passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000#b6425eaa salt1:bytes salt2:bytes = PasswordKdfAlgo;
|
passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow#3a912d4a salt1:bytes salt2:bytes g:int p:bytes = PasswordKdfAlgo;
|
||||||
|
|
||||||
securePasswordKdfAlgoUnknown#4a8537 = SecurePasswordKdfAlgo;
|
securePasswordKdfAlgoUnknown#4a8537 = SecurePasswordKdfAlgo;
|
||||||
securePasswordKdfAlgoPBKDF2HMACSHA512iter100000#bbf2dda0 salt:bytes = SecurePasswordKdfAlgo;
|
securePasswordKdfAlgoPBKDF2HMACSHA512iter100000#bbf2dda0 salt:bytes = SecurePasswordKdfAlgo;
|
||||||
@ -908,6 +908,9 @@ securePasswordKdfAlgoSHA512#86471d92 salt:bytes = SecurePasswordKdfAlgo;
|
|||||||
|
|
||||||
secureSecretSettings#1527bcac secure_algo:SecurePasswordKdfAlgo secure_secret:bytes secure_secret_id:long = SecureSecretSettings;
|
secureSecretSettings#1527bcac secure_algo:SecurePasswordKdfAlgo secure_secret:bytes secure_secret_id:long = SecureSecretSettings;
|
||||||
|
|
||||||
|
inputCheckPasswordEmpty#9880f658 = InputCheckPasswordSRP;
|
||||||
|
inputCheckPasswordSRP#d27ff082 srp_id:long A:bytes M1:bytes = InputCheckPasswordSRP;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
@ -927,7 +930,7 @@ auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
|
|||||||
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
|
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
|
||||||
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
|
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
|
||||||
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
|
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
|
||||||
auth.checkPassword#a63011e password_hash:bytes = auth.Authorization;
|
auth.checkPassword#d18b4d16 password:InputCheckPasswordSRP = auth.Authorization;
|
||||||
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
|
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
|
||||||
auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
|
auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
|
||||||
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
|
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
|
||||||
@ -956,11 +959,11 @@ account.updateDeviceLocked#38df3532 period:int = Bool;
|
|||||||
account.getAuthorizations#e320c158 = account.Authorizations;
|
account.getAuthorizations#e320c158 = account.Authorizations;
|
||||||
account.resetAuthorization#df77f3bc hash:long = Bool;
|
account.resetAuthorization#df77f3bc hash:long = Bool;
|
||||||
account.getPassword#548a30f5 = account.Password;
|
account.getPassword#548a30f5 = account.Password;
|
||||||
account.getPasswordSettings#bc8d11bb current_password_hash:bytes = account.PasswordSettings;
|
account.getPasswordSettings#9cd4eaf9 password:InputCheckPasswordSRP = account.PasswordSettings;
|
||||||
account.updatePasswordSettings#fa7c4b86 current_password_hash:bytes new_settings:account.PasswordInputSettings = Bool;
|
account.updatePasswordSettings#a59b102f password:InputCheckPasswordSRP new_settings:account.PasswordInputSettings = Bool;
|
||||||
account.sendConfirmPhoneCode#1516d7bd flags:# allow_flashcall:flags.0?true hash:string current_number:flags.0?Bool = auth.SentCode;
|
account.sendConfirmPhoneCode#1516d7bd flags:# allow_flashcall:flags.0?true hash:string current_number:flags.0?Bool = auth.SentCode;
|
||||||
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
|
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
|
||||||
account.getTmpPassword#4a82327e password_hash:bytes period:int = account.TmpPassword;
|
account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
|
||||||
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
|
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
|
||||||
account.resetWebAuthorization#2d01b9ef hash:long = Bool;
|
account.resetWebAuthorization#2d01b9ef hash:long = Bool;
|
||||||
account.resetWebAuthorizations#682d2594 = Bool;
|
account.resetWebAuthorizations#682d2594 = Bool;
|
||||||
|
Binary file not shown.
@ -614,8 +614,10 @@ void AuthManager::check_password(uint64 query_id, string password) {
|
|||||||
return on_query_error(query_id, Status::Error(8, "checkAuthenticationPassword unexpected"));
|
return on_query_error(query_id, Status::Error(8, "checkAuthenticationPassword unexpected"));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hash = PasswordManager::calc_password_hash(password, wait_password_state_.current_client_salt_,
|
auto hash = PasswordManager::get_input_check_password(password, wait_password_state_.current_client_salt_,
|
||||||
wait_password_state_.current_server_salt_);
|
wait_password_state_.current_server_salt_,
|
||||||
|
wait_password_state_.srp_g_, wait_password_state_.srp_p_,
|
||||||
|
wait_password_state_.srp_B_, wait_password_state_.srp_id_);
|
||||||
|
|
||||||
on_new_query(query_id);
|
on_new_query(query_id);
|
||||||
start_net_query(NetQueryType::CheckPassword,
|
start_net_query(NetQueryType::CheckPassword,
|
||||||
@ -755,11 +757,15 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
|
|||||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||||
// TODO we need to abort authorization somehow
|
// TODO we need to abort authorization somehow
|
||||||
break;
|
break;
|
||||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000::ID: {
|
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||||
auto algo = move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000>(
|
auto algo = move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||||
password->current_algo_);
|
password->current_algo_);
|
||||||
wait_password_state_.current_client_salt_ = algo->salt1_.as_slice().str();
|
wait_password_state_.current_client_salt_ = algo->salt1_.as_slice().str();
|
||||||
wait_password_state_.current_server_salt_ = algo->salt2_.as_slice().str();
|
wait_password_state_.current_server_salt_ = algo->salt2_.as_slice().str();
|
||||||
|
wait_password_state_.srp_g_ = algo->g_;
|
||||||
|
wait_password_state_.srp_p_ = algo->p_.as_slice().str();
|
||||||
|
wait_password_state_.srp_B_ = password->srp_B_.as_slice().str();
|
||||||
|
wait_password_state_.srp_id_ = password->srp_id_;
|
||||||
wait_password_state_.hint_ = std::move(password->hint_);
|
wait_password_state_.hint_ = std::move(password->hint_);
|
||||||
wait_password_state_.has_recovery_ =
|
wait_password_state_.has_recovery_ =
|
||||||
(password->flags_ & telegram_api::account_password::HAS_RECOVERY_MASK) != 0;
|
(password->flags_ & telegram_api::account_password::HAS_RECOVERY_MASK) != 0;
|
||||||
|
@ -198,6 +198,10 @@ class AuthManager : public NetActor {
|
|||||||
struct WaitPasswordState {
|
struct WaitPasswordState {
|
||||||
string current_client_salt_;
|
string current_client_salt_;
|
||||||
string current_server_salt_;
|
string current_server_salt_;
|
||||||
|
int32 srp_g_ = 0;
|
||||||
|
string srp_p_;
|
||||||
|
string srp_B_;
|
||||||
|
int64 srp_id_ = 0;
|
||||||
string hint_;
|
string hint_;
|
||||||
bool has_recovery_ = false;
|
bool has_recovery_ = false;
|
||||||
string email_address_pattern_;
|
string email_address_pattern_;
|
||||||
|
@ -59,6 +59,10 @@ void AuthManager::WaitPasswordState::store(T &storer) const {
|
|||||||
using td::store;
|
using td::store;
|
||||||
store(current_client_salt_, storer);
|
store(current_client_salt_, storer);
|
||||||
store(current_server_salt_, storer);
|
store(current_server_salt_, storer);
|
||||||
|
store(srp_g_, storer);
|
||||||
|
store(srp_p_, storer);
|
||||||
|
store(srp_B_, storer);
|
||||||
|
store(srp_id_, storer);
|
||||||
store(hint_, storer);
|
store(hint_, storer);
|
||||||
store(has_recovery_, storer);
|
store(has_recovery_, storer);
|
||||||
store(email_address_pattern_, storer);
|
store(email_address_pattern_, storer);
|
||||||
@ -69,6 +73,10 @@ void AuthManager::WaitPasswordState::parse(T &parser) {
|
|||||||
using td::parse;
|
using td::parse;
|
||||||
parse(current_client_salt_, parser);
|
parse(current_client_salt_, parser);
|
||||||
parse(current_server_salt_, parser);
|
parse(current_server_salt_, parser);
|
||||||
|
parse(srp_g_, parser);
|
||||||
|
parse(srp_p_, parser);
|
||||||
|
parse(srp_B_, parser);
|
||||||
|
parse(srp_id_, parser);
|
||||||
parse(hint_, parser);
|
parse(hint_, parser);
|
||||||
parse(has_recovery_, parser);
|
parse(has_recovery_, parser);
|
||||||
parse(email_address_pattern_, parser);
|
parse(email_address_pattern_, parser);
|
||||||
@ -79,9 +87,11 @@ void AuthManager::DbState::store(T &storer) const {
|
|||||||
using td::store;
|
using td::store;
|
||||||
bool has_terms_of_service = !terms_of_service_.get_id().empty();
|
bool has_terms_of_service = !terms_of_service_.get_id().empty();
|
||||||
bool is_pbkdf2_supported = true;
|
bool is_pbkdf2_supported = true;
|
||||||
|
bool is_srp_supported = true;
|
||||||
BEGIN_STORE_FLAGS();
|
BEGIN_STORE_FLAGS();
|
||||||
STORE_FLAG(has_terms_of_service);
|
STORE_FLAG(has_terms_of_service);
|
||||||
STORE_FLAG(is_pbkdf2_supported);
|
STORE_FLAG(is_pbkdf2_supported);
|
||||||
|
STORE_FLAG(is_srp_supported);
|
||||||
END_STORE_FLAGS();
|
END_STORE_FLAGS();
|
||||||
store(state_, storer);
|
store(state_, storer);
|
||||||
store(api_id_, storer);
|
store(api_id_, storer);
|
||||||
@ -106,10 +116,12 @@ void AuthManager::DbState::parse(T &parser) {
|
|||||||
using td::parse;
|
using td::parse;
|
||||||
bool has_terms_of_service = false;
|
bool has_terms_of_service = false;
|
||||||
bool is_pbkdf2_supported = false;
|
bool is_pbkdf2_supported = false;
|
||||||
|
bool is_srp_supported = false;
|
||||||
if (parser.version() >= static_cast<int32>(Version::AddTermsOfService)) {
|
if (parser.version() >= static_cast<int32>(Version::AddTermsOfService)) {
|
||||||
BEGIN_PARSE_FLAGS();
|
BEGIN_PARSE_FLAGS();
|
||||||
PARSE_FLAG(has_terms_of_service);
|
PARSE_FLAG(has_terms_of_service);
|
||||||
PARSE_FLAG(is_pbkdf2_supported);
|
PARSE_FLAG(is_pbkdf2_supported);
|
||||||
|
PARSE_FLAG(is_srp_supported);
|
||||||
END_PARSE_FLAGS();
|
END_PARSE_FLAGS();
|
||||||
}
|
}
|
||||||
parse(state_, parser);
|
parse(state_, parser);
|
||||||
@ -130,6 +142,9 @@ void AuthManager::DbState::parse(T &parser) {
|
|||||||
if (!is_pbkdf2_supported) {
|
if (!is_pbkdf2_supported) {
|
||||||
return parser.set_error("Need PBKDF2 support");
|
return parser.set_error("Need PBKDF2 support");
|
||||||
}
|
}
|
||||||
|
if (!is_srp_supported) {
|
||||||
|
return parser.set_error("Need SRP support");
|
||||||
|
}
|
||||||
parse(wait_password_state_, parser);
|
parse(wait_password_state_, parser);
|
||||||
} else {
|
} else {
|
||||||
parser.set_error(PSTRING() << "Unexpected " << tag("state", static_cast<int32>(state_)));
|
parser.set_error(PSTRING() << "Unexpected " << tag("state", static_cast<int32>(state_)));
|
||||||
|
@ -6,13 +6,17 @@
|
|||||||
//
|
//
|
||||||
#include "td/telegram/PasswordManager.h"
|
#include "td/telegram/PasswordManager.h"
|
||||||
|
|
||||||
|
#include "td/telegram/DhCache.h"
|
||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
#include "td/telegram/logevent/LogEvent.h"
|
#include "td/telegram/logevent/LogEvent.h"
|
||||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||||
#include "td/telegram/SecureStorage.h"
|
#include "td/telegram/SecureStorage.h"
|
||||||
|
|
||||||
|
#include "td/mtproto/crypto.h"
|
||||||
|
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/crypto.h"
|
#include "td/utils/crypto.h"
|
||||||
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/Random.h"
|
#include "td/utils/Random.h"
|
||||||
#include "td/utils/Slice.h"
|
#include "td/utils/Slice.h"
|
||||||
@ -34,20 +38,104 @@ static void hash_sha256(Slice data, Slice salt, MutableSlice dest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BufferSlice PasswordManager::calc_password_hash(Slice password, Slice client_salt, Slice server_salt) {
|
BufferSlice PasswordManager::calc_password_hash(Slice password, Slice client_salt, Slice server_salt) {
|
||||||
if (password.empty()) {
|
|
||||||
return BufferSlice();
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferSlice buf(32);
|
BufferSlice buf(32);
|
||||||
hash_sha256(password, client_salt, buf.as_slice());
|
hash_sha256(password, client_salt, buf.as_slice());
|
||||||
hash_sha256(buf.as_slice(), server_salt, buf.as_slice());
|
hash_sha256(buf.as_slice(), server_salt, buf.as_slice());
|
||||||
BufferSlice hash(64);
|
BufferSlice hash(64);
|
||||||
pbkdf2_sha512(buf.as_slice(), client_salt, 100000, hash.as_slice());
|
pbkdf2_sha512(buf.as_slice(), client_salt, 100000, hash.as_slice());
|
||||||
return hash;
|
hash_sha256(hash.as_slice(), server_salt, buf.as_slice());
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferSlice PasswordManager::calc_password_hash(Slice password, const PasswordState &state) const {
|
Result<BufferSlice> PasswordManager::calc_password_srp_hash(Slice password, Slice client_salt, Slice server_salt,
|
||||||
return calc_password_hash(password, state.current_client_salt, state.current_server_salt);
|
int32 g, Slice p) {
|
||||||
|
TRY_STATUS(DhHandshake::check_config(g, p, DhCache::instance()));
|
||||||
|
|
||||||
|
auto hash = calc_password_hash(password, client_salt, server_salt);
|
||||||
|
auto p_bn = BigNum::from_binary(p);
|
||||||
|
BigNum g_bn;
|
||||||
|
g_bn.set_value(g);
|
||||||
|
auto x_bn = BigNum::from_binary(hash.as_slice());
|
||||||
|
|
||||||
|
BigNumContext ctx;
|
||||||
|
BigNum v_bn;
|
||||||
|
BigNum::mod_exp(v_bn, g_bn, x_bn, p_bn, ctx);
|
||||||
|
|
||||||
|
return BufferSlice(v_bn.to_binary(256));
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_check_password(
|
||||||
|
Slice password, Slice client_salt, Slice server_salt, int32 g, Slice p, Slice B, int64 id) {
|
||||||
|
if (password.empty()) {
|
||||||
|
return make_tl_object<telegram_api::inputCheckPasswordEmpty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DhHandshake::check_config(g, p, DhCache::instance()).is_error()) {
|
||||||
|
LOG(ERROR) << "Receive invalid config " << g << " " << format::escaped(p);
|
||||||
|
return make_tl_object<telegram_api::inputCheckPasswordEmpty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p_bn = BigNum::from_binary(p);
|
||||||
|
auto B_bn = BigNum::from_binary(B);
|
||||||
|
auto zero = BigNum::from_decimal("0").move_as_ok();
|
||||||
|
if (BigNum::compare(zero, B_bn) != -1 || BigNum::compare(B_bn, p_bn) != -1 || B.size() != 256) {
|
||||||
|
LOG(ERROR) << "Receive invalid value of B(" << B.size() << "): " << B_bn << " " << p_bn;
|
||||||
|
return make_tl_object<telegram_api::inputCheckPasswordEmpty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
BigNum g_bn;
|
||||||
|
g_bn.set_value(g);
|
||||||
|
auto g_padded = g_bn.to_binary(256);
|
||||||
|
|
||||||
|
auto x = calc_password_hash(password, client_salt, server_salt);
|
||||||
|
auto x_bn = BigNum::from_binary(x.as_slice());
|
||||||
|
|
||||||
|
BufferSlice a(2048 / 8);
|
||||||
|
Random::secure_bytes(a.as_slice());
|
||||||
|
auto a_bn = BigNum::from_binary(a.as_slice());
|
||||||
|
|
||||||
|
BigNumContext ctx;
|
||||||
|
BigNum A_bn;
|
||||||
|
BigNum::mod_exp(A_bn, g_bn, a_bn, p_bn, ctx);
|
||||||
|
string A = A_bn.to_binary(256);
|
||||||
|
|
||||||
|
string u = sha256(PSLICE() << A << B);
|
||||||
|
auto u_bn = BigNum::from_binary(u);
|
||||||
|
string k = sha256(PSLICE() << p << g_padded);
|
||||||
|
auto k_bn = BigNum::from_binary(k);
|
||||||
|
|
||||||
|
BigNum v_bn;
|
||||||
|
BigNum::mod_exp(v_bn, g_bn, x_bn, p_bn, ctx);
|
||||||
|
BigNum kv_bn;
|
||||||
|
BigNum::mod_mul(kv_bn, k_bn, v_bn, p_bn, ctx);
|
||||||
|
BigNum t_bn;
|
||||||
|
BigNum::sub(t_bn, B_bn, kv_bn);
|
||||||
|
if (BigNum::compare(t_bn, zero) == -1) {
|
||||||
|
BigNum::add(t_bn, t_bn, p_bn);
|
||||||
|
}
|
||||||
|
BigNum exp_bn;
|
||||||
|
BigNum::mul(exp_bn, u_bn, x_bn, ctx);
|
||||||
|
BigNum::add(exp_bn, exp_bn, a_bn);
|
||||||
|
|
||||||
|
BigNum S_bn;
|
||||||
|
BigNum::mod_exp(S_bn, t_bn, exp_bn, p_bn, ctx);
|
||||||
|
string S = S_bn.to_binary(256);
|
||||||
|
auto K = sha256(S);
|
||||||
|
|
||||||
|
auto h1 = sha256(p);
|
||||||
|
auto h2 = sha256(g_padded);
|
||||||
|
for (size_t i = 0; i < h1.size(); i++) {
|
||||||
|
h1[i] = static_cast<char>(static_cast<unsigned char>(h1[i]) ^ static_cast<unsigned char>(h2[i]));
|
||||||
|
}
|
||||||
|
auto M = sha256(PSLICE() << h1 << sha256(client_salt) << sha256(server_salt) << A << B << K);
|
||||||
|
|
||||||
|
return make_tl_object<telegram_api::inputCheckPasswordSRP>(id, BufferSlice(A), BufferSlice(M));
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_check_password(
|
||||||
|
Slice password, const PasswordState &state) const {
|
||||||
|
return get_input_check_password(password, state.current_client_salt, state.current_server_salt, state.current_srp_g,
|
||||||
|
state.current_srp_p, state.current_srp_B, state.current_srp_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasswordManager::set_password(string current_password, string new_password, string new_hint,
|
void PasswordManager::set_password(string current_password, string new_password, string new_hint,
|
||||||
@ -164,7 +252,7 @@ void PasswordManager::drop_temp_password() {
|
|||||||
|
|
||||||
void PasswordManager::do_create_temp_password(string password, int32 timeout, PasswordState &&password_state,
|
void PasswordManager::do_create_temp_password(string password, int32 timeout, PasswordState &&password_state,
|
||||||
Promise<TempPasswordState> promise) {
|
Promise<TempPasswordState> promise) {
|
||||||
auto hash = calc_password_hash(password, password_state);
|
auto hash = get_input_check_password(password, password_state);
|
||||||
send_with_promise(
|
send_with_promise(
|
||||||
G()->net_query_creator().create(create_storer(telegram_api::account_getTmpPassword(std::move(hash), timeout))),
|
G()->net_query_creator().create(create_storer(telegram_api::account_getTmpPassword(std::move(hash), timeout))),
|
||||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||||
@ -235,7 +323,7 @@ Result<secure_storage::Secret> PasswordManager::decrypt_secure_secret(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PasswordManager::do_get_full_state(string password, PasswordState state, Promise<PasswordFullState> promise) {
|
void PasswordManager::do_get_full_state(string password, PasswordState state, Promise<PasswordFullState> promise) {
|
||||||
auto hash = calc_password_hash(password, state);
|
auto hash = get_input_check_password(password, state);
|
||||||
send_with_promise(
|
send_with_promise(
|
||||||
G()->net_query_creator().create(create_storer(telegram_api::account_getPasswordSettings(std::move(hash)))),
|
G()->net_query_creator().create(create_storer(telegram_api::account_getPasswordSettings(std::move(hash)))),
|
||||||
PromiseCreator::lambda(
|
PromiseCreator::lambda(
|
||||||
@ -390,10 +478,16 @@ void PasswordManager::do_update_password_settings(UpdateSettings update_settings
|
|||||||
if (!update_settings.new_password.empty()) {
|
if (!update_settings.new_password.empty()) {
|
||||||
auto new_client_salt = create_salt(state.new_client_salt);
|
auto new_client_salt = create_salt(state.new_client_salt);
|
||||||
|
|
||||||
new_settings->new_password_hash_ =
|
auto new_hash = calc_password_srp_hash(update_settings.new_password, new_client_salt.as_slice(),
|
||||||
calc_password_hash(update_settings.new_password, new_client_salt.as_slice(), state.new_server_salt);
|
state.new_server_salt, state.new_srp_g, state.new_srp_p);
|
||||||
new_settings->new_algo_ = make_tl_object<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000>(
|
if (new_hash.is_error()) {
|
||||||
std::move(new_client_salt), BufferSlice(state.new_server_salt));
|
return promise.set_error(Status::Error(400, "Unable to change password, because it may be unsafe"));
|
||||||
|
}
|
||||||
|
new_settings->new_password_hash_ = new_hash.move_as_ok();
|
||||||
|
new_settings->new_algo_ =
|
||||||
|
make_tl_object<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||||
|
std::move(new_client_salt), BufferSlice(state.new_server_salt), state.new_srp_g,
|
||||||
|
BufferSlice(state.new_srp_p));
|
||||||
new_settings->hint_ = std::move(update_settings.new_hint);
|
new_settings->hint_ = std::move(update_settings.new_hint);
|
||||||
if (private_state.secret) {
|
if (private_state.secret) {
|
||||||
update_settings.update_secure_secret = true;
|
update_settings.update_secure_secret = true;
|
||||||
@ -429,10 +523,7 @@ void PasswordManager::do_update_password_settings(UpdateSettings update_settings
|
|||||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::EMAIL_MASK;
|
new_settings->flags_ |= telegram_api::account_passwordInputSettings::EMAIL_MASK;
|
||||||
new_settings->email_ = std::move(update_settings.recovery_email_address);
|
new_settings->email_ = std::move(update_settings.recovery_email_address);
|
||||||
}
|
}
|
||||||
BufferSlice current_hash;
|
auto current_hash = get_input_check_password(state.has_password ? update_settings.current_password : Slice(), state);
|
||||||
if (state.has_password) {
|
|
||||||
current_hash = calc_password_hash(update_settings.current_password, state);
|
|
||||||
}
|
|
||||||
auto query = G()->net_query_creator().create(
|
auto query = G()->net_query_creator().create(
|
||||||
create_storer(telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings))));
|
create_storer(telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings))));
|
||||||
|
|
||||||
@ -477,16 +568,21 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
|||||||
switch (password->current_algo_->get_id()) {
|
switch (password->current_algo_->get_id()) {
|
||||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||||
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
||||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000::ID: {
|
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||||
auto algo = move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000>(
|
auto algo =
|
||||||
password->current_algo_);
|
move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||||
|
password->current_algo_);
|
||||||
state.current_client_salt = algo->salt1_.as_slice().str();
|
state.current_client_salt = algo->salt1_.as_slice().str();
|
||||||
state.current_server_salt = algo->salt2_.as_slice().str();
|
state.current_server_salt = algo->salt2_.as_slice().str();
|
||||||
|
state.current_srp_g = algo->g_;
|
||||||
|
state.current_srp_p = algo->p_.as_slice().str();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
state.current_srp_B = password->srp_B_.as_slice().str();
|
||||||
|
state.current_srp_id = password->srp_id_;
|
||||||
state.password_hint = std::move(password->hint_);
|
state.password_hint = std::move(password->hint_);
|
||||||
state.has_recovery_email_address =
|
state.has_recovery_email_address =
|
||||||
(password->flags_ & telegram_api::account_password::HAS_RECOVERY_MASK) != 0;
|
(password->flags_ & telegram_api::account_password::HAS_RECOVERY_MASK) != 0;
|
||||||
@ -500,11 +596,14 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
|||||||
switch (password->new_algo_->get_id()) {
|
switch (password->new_algo_->get_id()) {
|
||||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||||
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
||||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000::ID: {
|
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||||
auto algo = move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000>(
|
auto algo =
|
||||||
password->new_algo_);
|
move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||||
|
password->new_algo_);
|
||||||
state.new_client_salt = algo->salt1_.as_slice().str();
|
state.new_client_salt = algo->salt1_.as_slice().str();
|
||||||
state.new_server_salt = algo->salt2_.as_slice().str();
|
state.new_server_salt = algo->salt2_.as_slice().str();
|
||||||
|
state.new_srp_g = algo->g_;
|
||||||
|
state.new_srp_p = algo->p_.as_slice().str();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -56,7 +56,9 @@ class PasswordManager : public NetQueryCallback {
|
|||||||
explicit PasswordManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
explicit PasswordManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferSlice calc_password_hash(Slice password, Slice client_salt, Slice server_salt);
|
static tl_object_ptr<telegram_api::InputCheckPasswordSRP> get_input_check_password(Slice password, Slice client_salt,
|
||||||
|
Slice server_salt, int32 g,
|
||||||
|
Slice p, Slice B, int64 id);
|
||||||
|
|
||||||
void get_state(Promise<State> promise);
|
void get_state(Promise<State> promise);
|
||||||
void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address,
|
void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address,
|
||||||
@ -96,8 +98,14 @@ class PasswordManager : public NetQueryCallback {
|
|||||||
|
|
||||||
string current_client_salt;
|
string current_client_salt;
|
||||||
string current_server_salt;
|
string current_server_salt;
|
||||||
|
int32 current_srp_g;
|
||||||
|
string current_srp_p;
|
||||||
|
string current_srp_B;
|
||||||
|
int64 current_srp_id;
|
||||||
string new_client_salt;
|
string new_client_salt;
|
||||||
string new_server_salt;
|
string new_server_salt;
|
||||||
|
int32 new_srp_g;
|
||||||
|
string new_srp_p;
|
||||||
|
|
||||||
string new_secure_salt;
|
string new_secure_salt;
|
||||||
|
|
||||||
@ -139,7 +147,13 @@ class PasswordManager : public NetQueryCallback {
|
|||||||
static Result<secure_storage::Secret> decrypt_secure_secret(
|
static Result<secure_storage::Secret> decrypt_secure_secret(
|
||||||
Slice password, tl_object_ptr<telegram_api::SecurePasswordKdfAlgo> algo_ptr, Slice secret, int64 secret_id);
|
Slice password, tl_object_ptr<telegram_api::SecurePasswordKdfAlgo> algo_ptr, Slice secret, int64 secret_id);
|
||||||
|
|
||||||
BufferSlice calc_password_hash(Slice password, const PasswordState &state) const;
|
static BufferSlice calc_password_hash(Slice password, Slice client_salt, Slice server_salt);
|
||||||
|
|
||||||
|
static Result<BufferSlice> calc_password_srp_hash(Slice password, Slice client_salt, Slice server_salt, int32 g,
|
||||||
|
Slice p);
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::InputCheckPasswordSRP> get_input_check_password(Slice password,
|
||||||
|
const PasswordState &state) const;
|
||||||
|
|
||||||
void update_password_settings(UpdateSettings update_settings, Promise<State> promise);
|
void update_password_settings(UpdateSettings update_settings, Promise<State> promise);
|
||||||
void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise<bool> promise);
|
void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise<bool> promise);
|
||||||
|
@ -1766,8 +1766,8 @@ class CliClient final : public Actor {
|
|||||||
|
|
||||||
vector<tl_object_ptr<td_api::LanguagePackString>> strings;
|
vector<tl_object_ptr<td_api::LanguagePackString>> strings;
|
||||||
strings.push_back(make_tl_object<td_api::languagePackStringValue>(key, "Ordinary value"));
|
strings.push_back(make_tl_object<td_api::languagePackStringValue>(key, "Ordinary value"));
|
||||||
strings.push_back(make_tl_object<td_api::languagePackStringPluralized>("Plu", "Zero", string("One\0One", 7), "Two", "Few",
|
strings.push_back(make_tl_object<td_api::languagePackStringPluralized>("Plu", "Zero", string("One\0One", 7),
|
||||||
"Many", "Other"));
|
"Two", "Few", "Many", "Other"));
|
||||||
strings.push_back(make_tl_object<td_api::languagePackStringDeleted>("DELETED"));
|
strings.push_back(make_tl_object<td_api::languagePackStringDeleted>("DELETED"));
|
||||||
|
|
||||||
send_request(make_tl_object<td_api::setCustomLanguage>(
|
send_request(make_tl_object<td_api::setCustomLanguage>(
|
||||||
|
@ -21,7 +21,7 @@ class HeaderStorer {
|
|||||||
}
|
}
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
constexpr int32 LAYER = 83;
|
constexpr int32 LAYER = 84;
|
||||||
|
|
||||||
using td::store;
|
using td::store;
|
||||||
// invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
|
// invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
|
||||||
|
Reference in New Issue
Block a user