mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
emergency update
This commit is contained in:
parent
5d846e0aaf
commit
9f351fc29f
87 changed files with 2486 additions and 655 deletions
|
@ -155,6 +155,13 @@ TEST(Tonlib, InitClose) {
|
|||
}
|
||||
}
|
||||
|
||||
td::Slice to_data(const td::SecureString &str) {
|
||||
return str.as_slice();
|
||||
}
|
||||
td::Slice to_data(const tonlib::SimpleEncryptionV2::Decrypted &str) {
|
||||
return str.data.as_slice();
|
||||
}
|
||||
|
||||
template <class Encryption>
|
||||
void test_encryption() {
|
||||
std::string secret = "secret";
|
||||
|
@ -164,7 +171,7 @@ void test_encryption() {
|
|||
auto encrypted_data = Encryption::encrypt_data(data, secret);
|
||||
LOG(ERROR) << encrypted_data.size();
|
||||
auto decrypted_data = Encryption::decrypt_data(encrypted_data, secret).move_as_ok();
|
||||
CHECK(data == decrypted_data);
|
||||
CHECK(data == to_data(decrypted_data));
|
||||
Encryption::decrypt_data(encrypted_data, wrong_secret).ensure_error();
|
||||
Encryption::decrypt_data("", secret).ensure_error();
|
||||
Encryption::decrypt_data(std::string(32, 'a'), secret).ensure_error();
|
||||
|
@ -177,7 +184,7 @@ void test_encryption() {
|
|||
auto data = td::rand_string('a', 'z', static_cast<int>(i));
|
||||
auto encrypted_data = Encryption::encrypt_data(data, secret);
|
||||
auto decrypted_data = Encryption::decrypt_data(encrypted_data, secret).move_as_ok();
|
||||
CHECK(data == decrypted_data);
|
||||
CHECK(data == to_data(decrypted_data));
|
||||
}
|
||||
}
|
||||
TEST(Tonlib, SimpleEncryption) {
|
||||
|
@ -199,24 +206,33 @@ TEST(Tonlib, SimpleEncryptionAsym) {
|
|||
auto encrypted_data = SimpleEncryptionV2::encrypt_data(data, public_key, other_private_key).move_as_ok();
|
||||
LOG(ERROR) << encrypted_data.size();
|
||||
auto decrypted_data = SimpleEncryptionV2::decrypt_data(encrypted_data, private_key).move_as_ok();
|
||||
CHECK(data == decrypted_data);
|
||||
CHECK(data == decrypted_data.data);
|
||||
auto decrypted_data2 = SimpleEncryptionV2::decrypt_data(encrypted_data, other_private_key).move_as_ok();
|
||||
CHECK(data == decrypted_data2);
|
||||
CHECK(data == decrypted_data2.data);
|
||||
|
||||
CHECK(decrypted_data.proof == decrypted_data2.proof);
|
||||
|
||||
auto decrypted_data3 =
|
||||
SimpleEncryptionV2::decrypt_data_with_proof(encrypted_data, decrypted_data.proof).move_as_ok();
|
||||
CHECK(data == decrypted_data3);
|
||||
|
||||
SimpleEncryptionV2::decrypt_data(encrypted_data, wrong_private_key).ensure_error();
|
||||
SimpleEncryptionV2::decrypt_data("", private_key).ensure_error();
|
||||
SimpleEncryptionV2::decrypt_data(std::string(32, 'a'), private_key).ensure_error();
|
||||
SimpleEncryptionV2::decrypt_data(std::string(33, 'a'), private_key).ensure_error();
|
||||
SimpleEncryptionV2::decrypt_data(std::string(64, 'a'), private_key).ensure_error();
|
||||
SimpleEncryptionV2::decrypt_data(std::string(128, 'a'), private_key).ensure_error();
|
||||
|
||||
SimpleEncryptionV2::decrypt_data_with_proof(encrypted_data, decrypted_data.proof, "bad salt").ensure_error();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 255; i++) {
|
||||
auto data = td::rand_string('a', 'z', static_cast<int>(i));
|
||||
auto encrypted_data = SimpleEncryptionV2::encrypt_data(data, public_key, other_private_key).move_as_ok();
|
||||
auto decrypted_data = SimpleEncryptionV2::decrypt_data(encrypted_data, private_key).move_as_ok();
|
||||
CHECK(data == decrypted_data);
|
||||
CHECK(data == decrypted_data.data);
|
||||
auto decrypted_data2 = SimpleEncryptionV2::decrypt_data(encrypted_data, other_private_key).move_as_ok();
|
||||
CHECK(data == decrypted_data2);
|
||||
CHECK(data == decrypted_data2.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,19 +534,30 @@ TEST(Tonlib, KeysApi) {
|
|||
auto other_public_key = td::Ed25519::generate_private_key().move_as_ok().get_public_key().move_as_ok();
|
||||
std::string text = "hello world";
|
||||
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::msg_Data>> elements;
|
||||
elements.push_back(make_object<tonlib_api::msg_dataEncryptedText>(
|
||||
SimpleEncryptionV2::encrypt_data(text, other_public_key, pkey).move_as_ok().as_slice().str()));
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::msg_dataEncrypted>> elements;
|
||||
td::Slice addr = "Ef9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfYFX";
|
||||
auto encrypted = SimpleEncryptionV2::encrypt_data(text, other_public_key, pkey, addr).move_as_ok().as_slice().str();
|
||||
elements.push_back(make_object<tonlib_api::msg_dataEncrypted>(
|
||||
make_object<tonlib_api::accountAddress>(addr.str()), make_object<tonlib_api::msg_dataEncryptedText>(encrypted)));
|
||||
|
||||
auto decrypted =
|
||||
sync_send(client, make_object<tonlib_api::msg_decrypt>(
|
||||
make_object<tonlib_api::inputKeyRegular>(
|
||||
make_object<tonlib_api::key>(key->public_key_, raw_imported_key->secret_.copy()),
|
||||
new_local_password.copy()),
|
||||
make_object<tonlib_api::msg_dataArray>(std::move(elements))))
|
||||
make_object<tonlib_api::msg_dataEncryptedArray>(std::move(elements))))
|
||||
.move_as_ok();
|
||||
|
||||
downcast_call(*decrypted->elements_[0],
|
||||
auto proof = decrypted->elements_[0]->proof_;
|
||||
downcast_call(*decrypted->elements_[0]->data_,
|
||||
td::overloaded([](auto &) { UNREACHABLE(); },
|
||||
[&](tonlib_api::msg_dataDecryptedText &decrypted) { CHECK(decrypted.text_ == text); }));
|
||||
auto decrypted2 = sync_send(client, make_object<tonlib_api::msg_decryptWithProof>(
|
||||
proof, make_object<tonlib_api::msg_dataEncrypted>(
|
||||
make_object<tonlib_api::accountAddress>(addr.str()),
|
||||
make_object<tonlib_api::msg_dataEncryptedText>(encrypted))))
|
||||
.move_as_ok();
|
||||
downcast_call(*decrypted2,
|
||||
td::overloaded([](auto &) { UNREACHABLE(); },
|
||||
[&](tonlib_api::msg_dataDecryptedText &decrypted) { CHECK(decrypted.text_ == text); }));
|
||||
}
|
||||
|
|
|
@ -392,9 +392,9 @@ td::Status transfer_grams(Client& client, const Wallet& wallet, std::string addr
|
|||
if (transfer_all) {
|
||||
ASSERT_EQ(amount - first_fee, txn->in_msg_->value_);
|
||||
} else {
|
||||
ASSERT_EQ(new_src_state.address, txn->in_msg_->source_);
|
||||
ASSERT_EQ(new_src_state.address, txn->in_msg_->source_->account_address_);
|
||||
}
|
||||
ASSERT_EQ(new_src_state.address, txn->in_msg_->source_);
|
||||
ASSERT_EQ(new_src_state.address, txn->in_msg_->source_->account_address_);
|
||||
if (!encrypt) {
|
||||
ASSERT_EQ(message, read_text(*txn->in_msg_->msg_data_));
|
||||
}
|
||||
|
|
|
@ -1368,6 +1368,7 @@ bool TonlibClient::is_static_request(td::int32 id) {
|
|||
case tonlib_api::encrypt::ID:
|
||||
case tonlib_api::decrypt::ID:
|
||||
case tonlib_api::kdf::ID:
|
||||
case tonlib_api::msg_decryptWithProof::ID:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -1841,38 +1842,41 @@ struct ToRawTransactions {
|
|||
auto body_cell = vm::CellBuilder().append_cellslice(*body).finalize();
|
||||
auto body_hash = body_cell->get_hash().as_slice().str();
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::msg_Data> data;
|
||||
if (body->size() >= 32 && static_cast<td::uint32>(body->prefetch_long(32)) <= 1) {
|
||||
auto type = body.write().fetch_long(32);
|
||||
td::Status status;
|
||||
auto get_data = [body = std::move(body), body_cell, this](td::Slice salt) mutable {
|
||||
tonlib_api::object_ptr<tonlib_api::msg_Data> data;
|
||||
if (body->size() >= 32 && static_cast<td::uint32>(body->prefetch_long(32)) <= 1) {
|
||||
auto type = body.write().fetch_long(32);
|
||||
td::Status status;
|
||||
|
||||
auto r_body_message = vm::CellString::load(body.write());
|
||||
LOG_IF(WARNING, r_body_message.is_error()) << "Failed to parse a message: " << r_body_message.error();
|
||||
auto r_body_message = vm::CellString::load(body.write());
|
||||
LOG_IF(WARNING, r_body_message.is_error()) << "Failed to parse a message: " << r_body_message.error();
|
||||
|
||||
if (r_body_message.is_ok()) {
|
||||
if (type == 0) {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataText>(r_body_message.move_as_ok());
|
||||
} else {
|
||||
LOG(ERROR) << "TRY DECRYPT";
|
||||
auto encrypted_message = r_body_message.move_as_ok();
|
||||
auto r_decrypted_message = [&]() -> td::Result<std::string> {
|
||||
if (!private_key_) {
|
||||
return TonlibError::EmptyField("private_key");
|
||||
}
|
||||
TRY_RESULT(decrypted, SimpleEncryptionV2::decrypt_data(encrypted_message, private_key_.value()));
|
||||
return decrypted.as_slice().str();
|
||||
}();
|
||||
if (r_decrypted_message.is_ok()) {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataDecryptedText>(r_decrypted_message.move_as_ok());
|
||||
if (r_body_message.is_ok()) {
|
||||
if (type == 0) {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataText>(r_body_message.move_as_ok());
|
||||
} else {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataEncryptedText>(encrypted_message);
|
||||
LOG(ERROR) << "TRY DECRYPT";
|
||||
auto encrypted_message = r_body_message.move_as_ok();
|
||||
auto r_decrypted_message = [&]() -> td::Result<std::string> {
|
||||
if (!private_key_) {
|
||||
return TonlibError::EmptyField("private_key");
|
||||
}
|
||||
TRY_RESULT(decrypted, SimpleEncryptionV2::decrypt_data(encrypted_message, private_key_.value(), salt));
|
||||
return decrypted.data.as_slice().str();
|
||||
}();
|
||||
if (r_decrypted_message.is_ok()) {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataDecryptedText>(r_decrypted_message.move_as_ok());
|
||||
} else {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataEncryptedText>(encrypted_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!data) {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataRaw>(to_bytes(std::move(body_cell)));
|
||||
}
|
||||
if (!data) {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataRaw>(to_bytes(std::move(body_cell)));
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
auto tag = block::gen::CommonMsgInfo().get_tag(*message.info);
|
||||
if (tag < 0) {
|
||||
|
@ -1892,9 +1896,10 @@ struct ToRawTransactions {
|
|||
TRY_RESULT(ihr_fee, to_balance(msg_info.ihr_fee));
|
||||
auto created_lt = static_cast<td::int64>(msg_info.created_lt);
|
||||
|
||||
return tonlib_api::make_object<tonlib_api::raw_message>(std::move(src), std::move(dest), balance, fwd_fee,
|
||||
ihr_fee, created_lt, std::move(body_hash),
|
||||
std::move(data));
|
||||
return tonlib_api::make_object<tonlib_api::raw_message>(
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(src),
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(std::move(dest)), balance, fwd_fee, ihr_fee, created_lt,
|
||||
std::move(body_hash), get_data(src));
|
||||
}
|
||||
case block::gen::CommonMsgInfo::ext_in_msg_info: {
|
||||
block::gen::CommonMsgInfo::Record_ext_in_msg_info msg_info;
|
||||
|
@ -1902,8 +1907,10 @@ struct ToRawTransactions {
|
|||
return td::Status::Error("Failed to unpack CommonMsgInfo::ext_in_msg_info");
|
||||
}
|
||||
TRY_RESULT(dest, to_std_address(msg_info.dest));
|
||||
return tonlib_api::make_object<tonlib_api::raw_message>("", std::move(dest), 0, 0, 0, 0, std::move(body_hash),
|
||||
std::move(data));
|
||||
return tonlib_api::make_object<tonlib_api::raw_message>(
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(),
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(std::move(dest)), 0, 0, 0, 0, std::move(body_hash),
|
||||
get_data(""));
|
||||
}
|
||||
case block::gen::CommonMsgInfo::ext_out_msg_info: {
|
||||
block::gen::CommonMsgInfo::Record_ext_out_msg_info msg_info;
|
||||
|
@ -1911,8 +1918,9 @@ struct ToRawTransactions {
|
|||
return td::Status::Error("Failed to unpack CommonMsgInfo::ext_out_msg_info");
|
||||
}
|
||||
TRY_RESULT(src, to_std_address(msg_info.src));
|
||||
return tonlib_api::make_object<tonlib_api::raw_message>(std::move(src), "", 0, 0, 0, 0, std::move(body_hash),
|
||||
std::move(data));
|
||||
return tonlib_api::make_object<tonlib_api::raw_message>(
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(src),
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(), 0, 0, 0, 0, std::move(body_hash), get_data(src));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2493,8 +2501,13 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
return TonlibError::MessageEncryption("Get public key (in destination)");
|
||||
}
|
||||
|
||||
auto addr = source_->get_address();
|
||||
addr.bounceable = true;
|
||||
addr.testnet = false;
|
||||
|
||||
TRY_RESULT_PREFIX(encrypted_message,
|
||||
SimpleEncryptionV2::encrypt_data(action.message, o_public_key.unwrap(), private_key_.value()),
|
||||
SimpleEncryptionV2::encrypt_data(action.message, o_public_key.unwrap(), private_key_.value(),
|
||||
addr.rserialize(true)),
|
||||
TonlibError::Internal());
|
||||
gift.message = encrypted_message.as_slice().str();
|
||||
gift.is_encrypted = true;
|
||||
|
@ -2569,7 +2582,7 @@ td::Status TonlibClient::do_request(tonlib_api::createQuery& request,
|
|||
}
|
||||
|
||||
td::Status TonlibClient::do_request(tonlib_api::msg_decrypt& request,
|
||||
td::Promise<object_ptr<tonlib_api::msg_dataArray>>&& promise) {
|
||||
td::Promise<object_ptr<tonlib_api::msg_dataDecryptedArray>>&& promise) {
|
||||
if (!request.input_key_) {
|
||||
return TonlibError::EmptyField("input_key");
|
||||
}
|
||||
|
@ -2577,27 +2590,44 @@ td::Status TonlibClient::do_request(tonlib_api::msg_decrypt& request,
|
|||
return TonlibError::EmptyField("data");
|
||||
}
|
||||
TRY_RESULT(input_key, from_tonlib(*request.input_key_));
|
||||
using ReturnType = tonlib_api::object_ptr<tonlib_api::msg_dataDecrypted>;
|
||||
make_request(
|
||||
int_api::GetPrivateKey{std::move(input_key)},
|
||||
promise.wrap([elements = std::move(request.data_)](auto key) mutable {
|
||||
auto private_key = td::Ed25519::PrivateKey(std::move(key.private_key));
|
||||
elements->elements_ = td::transform(std::move(elements->elements_), [&private_key](auto msg) {
|
||||
auto new_elements = td::transform(std::move(elements->elements_), [&private_key](auto msg) -> ReturnType {
|
||||
auto res = tonlib_api::make_object<tonlib_api::msg_dataDecrypted>();
|
||||
if (!msg) {
|
||||
return std::move(msg);
|
||||
return res;
|
||||
}
|
||||
if (!msg->data_) {
|
||||
return res;
|
||||
}
|
||||
res->data_ = std::move(msg->data_);
|
||||
if (!msg->source_) {
|
||||
return res;
|
||||
}
|
||||
auto r_account_address = get_account_address(msg->source_->account_address_);
|
||||
if (r_account_address.is_error()) {
|
||||
return res;
|
||||
}
|
||||
using ReturnType = tonlib_api::object_ptr<tonlib_api::msg_Data>;
|
||||
return downcast_call2<ReturnType>(
|
||||
*msg, td::overloaded([&msg](auto&) { return std::move(msg); },
|
||||
[&msg, &private_key](tonlib_api::msg_dataEncryptedText& encrypted) -> ReturnType {
|
||||
auto r_decrypted = SimpleEncryptionV2::decrypt_data(encrypted.text_, private_key);
|
||||
if (r_decrypted.is_error()) {
|
||||
return std::move(msg);
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::msg_dataDecryptedText>(
|
||||
r_decrypted.move_as_ok().as_slice().str());
|
||||
}));
|
||||
*res->data_,
|
||||
td::overloaded(
|
||||
[&res](auto&) { return std::move(res); },
|
||||
[&res, &private_key, &msg](tonlib_api::msg_dataEncryptedText& encrypted) -> ReturnType {
|
||||
auto r_decrypted =
|
||||
SimpleEncryptionV2::decrypt_data(encrypted.text_, private_key, msg->source_->account_address_);
|
||||
if (r_decrypted.is_error()) {
|
||||
return std::move(res);
|
||||
}
|
||||
auto decrypted = r_decrypted.move_as_ok();
|
||||
return tonlib_api::make_object<tonlib_api::msg_dataDecrypted>(
|
||||
decrypted.proof.as_slice().str(),
|
||||
tonlib_api::make_object<tonlib_api::msg_dataDecryptedText>(decrypted.data.as_slice().str()));
|
||||
}));
|
||||
});
|
||||
return std::move(elements);
|
||||
return tonlib_api::make_object<tonlib_api::msg_dataDecryptedArray>(std::move(new_elements));
|
||||
}));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
@ -3251,6 +3281,32 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const
|
|||
SimpleEncryption::kdf(request.password_, request.salt_, request.iterations_));
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
||||
const tonlib_api::msg_decryptWithProof& request) {
|
||||
if (!request.data_) {
|
||||
return status_to_tonlib_api(TonlibError::EmptyField("data"));
|
||||
}
|
||||
if (!request.data_->data_) {
|
||||
TonlibError::EmptyField("data.data");
|
||||
}
|
||||
if (!request.data_->source_) {
|
||||
TonlibError::EmptyField("data.source");
|
||||
}
|
||||
using ReturnType = tonlib_api::object_ptr<tonlib_api::msg_Data>;
|
||||
return downcast_call2<ReturnType>(
|
||||
*request.data_->data_,
|
||||
td::overloaded([&request](auto&) { return std::move(request.data_->data_); },
|
||||
[&request](tonlib_api::msg_dataEncryptedText& encrypted) -> ReturnType {
|
||||
auto r_decrypted = SimpleEncryptionV2::decrypt_data_with_proof(
|
||||
encrypted.text_, request.proof_, request.data_->source_->account_address_);
|
||||
if (r_decrypted.is_error()) {
|
||||
return std::move(request.data_->data_);
|
||||
}
|
||||
auto decrypted = r_decrypted.move_as_ok();
|
||||
return tonlib_api::make_object<tonlib_api::msg_dataDecryptedText>(decrypted.as_slice().str());
|
||||
}));
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(int_api::GetAccountState request,
|
||||
td::Promise<td::unique_ptr<AccountState>>&& promise) {
|
||||
auto actor_id = actor_id_++;
|
||||
|
@ -3399,4 +3455,9 @@ td::Status TonlibClient::do_request(const tonlib_api::kdf& request, P&&) {
|
|||
UNREACHABLE();
|
||||
return TonlibError::Internal();
|
||||
}
|
||||
template <class P>
|
||||
td::Status TonlibClient::do_request(const tonlib_api::msg_decryptWithProof& request, P&&) {
|
||||
UNREACHABLE();
|
||||
return TonlibError::Internal();
|
||||
}
|
||||
} // namespace tonlib
|
||||
|
|
|
@ -160,6 +160,8 @@ class TonlibClient : public td::actor::Actor {
|
|||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::decrypt& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::kdf& request);
|
||||
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::msg_decryptWithProof& request);
|
||||
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::runTests& request, P&&);
|
||||
template <class P>
|
||||
|
@ -194,6 +196,8 @@ class TonlibClient : public td::actor::Actor {
|
|||
td::Status do_request(const tonlib_api::decrypt& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::kdf& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::msg_decryptWithProof& request, P&&);
|
||||
|
||||
void make_any_request(tonlib_api::Function& function, QueryContext query_context,
|
||||
td::Promise<tonlib_api::object_ptr<tonlib_api::Object>>&& promise);
|
||||
|
@ -281,7 +285,8 @@ class TonlibClient : public td::actor::Actor {
|
|||
|
||||
td::Status do_request(tonlib_api::createQuery& request, td::Promise<object_ptr<tonlib_api::query_info>>&& promise);
|
||||
|
||||
td::Status do_request(tonlib_api::msg_decrypt& request, td::Promise<object_ptr<tonlib_api::msg_dataArray>>&& promise);
|
||||
td::Status do_request(tonlib_api::msg_decrypt& request,
|
||||
td::Promise<object_ptr<tonlib_api::msg_dataDecryptedArray>>&& promise);
|
||||
|
||||
td::int64 next_smc_id_{0};
|
||||
std::map<td::int64, td::unique_ptr<AccountState>> smcs_;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
namespace tonlib {
|
||||
td::AesCbcState SimpleEncryption::calc_aes_cbc_state_hash(td::Slice hash) {
|
||||
CHECK(hash.size() == 64);
|
||||
CHECK(hash.size() >= 48);
|
||||
td::SecureString key(32);
|
||||
key.as_mutable_slice().copy_from(hash.substr(0, 32));
|
||||
td::SecureString iv(16);
|
||||
|
@ -34,7 +34,7 @@ td::AesCbcState SimpleEncryption::calc_aes_cbc_state_hash(td::Slice hash) {
|
|||
td::AesCbcState SimpleEncryption::calc_aes_cbc_state_sha512(td::Slice seed) {
|
||||
td::SecureString hash(64);
|
||||
sha512(seed, hash.as_mutable_slice());
|
||||
return calc_aes_cbc_state_hash(hash.as_slice());
|
||||
return calc_aes_cbc_state_hash(hash.as_slice().substr(0, 48));
|
||||
}
|
||||
|
||||
td::SecureString SimpleEncryption::gen_random_prefix(td::int64 data_size, td::int64 min_padding) {
|
||||
|
@ -106,10 +106,10 @@ td::Result<td::SecureString> SimpleEncryption::decrypt_data(td::Slice encrypted_
|
|||
return td::SecureString(decrypted_data.as_slice().substr(prefix_size));
|
||||
}
|
||||
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::encrypt_data(td::Slice data,
|
||||
const td::Ed25519::PublicKey &public_key) {
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::encrypt_data(td::Slice data, const td::Ed25519::PublicKey &public_key,
|
||||
td::Slice salt) {
|
||||
TRY_RESULT(tmp_private_key, td::Ed25519::generate_private_key());
|
||||
return encrypt_data(data, public_key, tmp_private_key);
|
||||
return encrypt_data(data, public_key, tmp_private_key, salt);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -124,9 +124,10 @@ td::SecureString secure_xor(td::Slice a, td::Slice b) {
|
|||
} // namespace
|
||||
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::encrypt_data(td::Slice data, const td::Ed25519::PublicKey &public_key,
|
||||
const td::Ed25519::PrivateKey &private_key) {
|
||||
const td::Ed25519::PrivateKey &private_key,
|
||||
td::Slice salt) {
|
||||
TRY_RESULT(shared_secret, td::Ed25519::compute_shared_secret(public_key, private_key));
|
||||
auto encrypted = encrypt_data(data, shared_secret.as_slice());
|
||||
auto encrypted = encrypt_data(data, shared_secret.as_slice(), salt);
|
||||
TRY_RESULT(tmp_public_key, private_key.get_public_key());
|
||||
td::SecureString prefixed_encrypted(tmp_public_key.LENGTH + encrypted.size());
|
||||
prefixed_encrypted.as_mutable_slice().copy_from(tmp_public_key.as_octet_string());
|
||||
|
@ -136,8 +137,9 @@ td::Result<td::SecureString> SimpleEncryptionV2::encrypt_data(td::Slice data, co
|
|||
return std::move(prefixed_encrypted);
|
||||
}
|
||||
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::decrypt_data(td::Slice data,
|
||||
const td::Ed25519::PrivateKey &private_key) {
|
||||
td::Result<SimpleEncryptionV2::Decrypted> SimpleEncryptionV2::decrypt_data(td::Slice data,
|
||||
const td::Ed25519::PrivateKey &private_key,
|
||||
td::Slice salt) {
|
||||
if (data.size() < td::Ed25519::PublicKey::LENGTH) {
|
||||
return td::Status::Error("Failed to decrypte: data is too small");
|
||||
}
|
||||
|
@ -145,17 +147,19 @@ td::Result<td::SecureString> SimpleEncryptionV2::decrypt_data(td::Slice data,
|
|||
auto tmp_public_key =
|
||||
td::Ed25519::PublicKey(secure_xor(data.substr(0, td::Ed25519::PublicKey::LENGTH), public_key.as_octet_string()));
|
||||
TRY_RESULT(shared_secret, td::Ed25519::compute_shared_secret(tmp_public_key, private_key));
|
||||
TRY_RESULT(decrypted, decrypt_data(data.substr(td::Ed25519::PublicKey::LENGTH), shared_secret.as_slice()));
|
||||
TRY_RESULT(decrypted, decrypt_data(data.substr(td::Ed25519::PublicKey::LENGTH), shared_secret.as_slice(), salt));
|
||||
return std::move(decrypted);
|
||||
}
|
||||
td::SecureString SimpleEncryptionV2::encrypt_data(td::Slice data, td::Slice secret) {
|
||||
|
||||
td::SecureString SimpleEncryptionV2::encrypt_data(td::Slice data, td::Slice secret, td::Slice salt) {
|
||||
auto prefix = SimpleEncryption::gen_random_prefix(data.size(), 16);
|
||||
td::SecureString combined(prefix.size() + data.size());
|
||||
combined.as_mutable_slice().copy_from(prefix);
|
||||
combined.as_mutable_slice().substr(prefix.size()).copy_from(data);
|
||||
return encrypt_data_with_prefix(combined.as_slice(), secret);
|
||||
return encrypt_data_with_prefix(combined.as_slice(), secret, salt);
|
||||
}
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::decrypt_data(td::Slice encrypted_data, td::Slice secret) {
|
||||
|
||||
td::Result<std::pair<td::Slice, td::Slice>> unpack_encrypted_data(td::Slice encrypted_data) {
|
||||
if (encrypted_data.size() < 17) {
|
||||
return td::Status::Error("Failed to decrypt: data is too small");
|
||||
}
|
||||
|
@ -163,13 +167,18 @@ td::Result<td::SecureString> SimpleEncryptionV2::decrypt_data(td::Slice encrypte
|
|||
return td::Status::Error("Failed to decrypt: data size is not divisible by 16");
|
||||
}
|
||||
auto msg_key = encrypted_data.substr(0, 16);
|
||||
encrypted_data = encrypted_data.substr(16);
|
||||
auto data = encrypted_data.substr(16);
|
||||
return std::make_pair(msg_key, data);
|
||||
}
|
||||
|
||||
auto cbc_state = SimpleEncryption::calc_aes_cbc_state_hash(SimpleEncryption::combine_secrets(secret, msg_key));
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::do_decrypt(td::Slice cbc_state_secret, td::Slice msg_key,
|
||||
td::Slice encrypted_data, td::Slice salt) {
|
||||
auto cbc_state = SimpleEncryption::calc_aes_cbc_state_hash(cbc_state_secret);
|
||||
td::SecureString decrypted_data(encrypted_data.size(), 0);
|
||||
auto iv_copy = cbc_state.raw().key.copy();
|
||||
cbc_state.decrypt(encrypted_data, decrypted_data.as_mutable_slice());
|
||||
|
||||
auto data_hash = SimpleEncryption::combine_secrets(decrypted_data, secret);
|
||||
auto data_hash = SimpleEncryption::combine_secrets(salt, decrypted_data);
|
||||
auto got_msg_key = data_hash.as_slice().substr(0, 16);
|
||||
// check hash
|
||||
if (msg_key != got_msg_key) {
|
||||
|
@ -183,9 +192,35 @@ td::Result<td::SecureString> SimpleEncryptionV2::decrypt_data(td::Slice encrypte
|
|||
|
||||
return td::SecureString(decrypted_data.as_slice().substr(prefix_size));
|
||||
}
|
||||
td::SecureString SimpleEncryptionV2::encrypt_data_with_prefix(td::Slice data, td::Slice secret) {
|
||||
|
||||
td::Result<SimpleEncryptionV2::Decrypted> SimpleEncryptionV2::decrypt_data(td::Slice encrypted_data, td::Slice secret,
|
||||
td::Slice salt) {
|
||||
TRY_RESULT(p, unpack_encrypted_data(encrypted_data));
|
||||
auto msg_key = p.first;
|
||||
auto data = p.second;
|
||||
auto cbc_state_secret = td::SecureString(SimpleEncryption::combine_secrets(secret, msg_key).as_slice().substr(0, 48));
|
||||
TRY_RESULT(res, do_decrypt(cbc_state_secret.as_slice(), msg_key, data, salt));
|
||||
return Decrypted{std::move(cbc_state_secret), std::move(res)};
|
||||
}
|
||||
|
||||
td::Result<td::SecureString> SimpleEncryptionV2::decrypt_data_with_proof(td::Slice encrypted_data, td::Slice proof,
|
||||
td::Slice salt) {
|
||||
if (encrypted_data.size() < td::Ed25519::PublicKey::LENGTH) {
|
||||
return td::Status::Error("Failed to decrypte: data is too small");
|
||||
}
|
||||
if (proof.size() != 48) {
|
||||
return td::Status::Error("Invalid proof size");
|
||||
}
|
||||
encrypted_data = encrypted_data.substr(td::Ed25519::PublicKey::LENGTH);
|
||||
TRY_RESULT(p, unpack_encrypted_data(encrypted_data));
|
||||
auto msg_key = p.first;
|
||||
auto data = p.second;
|
||||
return do_decrypt(proof, msg_key, data, salt);
|
||||
}
|
||||
|
||||
td::SecureString SimpleEncryptionV2::encrypt_data_with_prefix(td::Slice data, td::Slice secret, td::Slice salt) {
|
||||
CHECK(data.size() % 16 == 0);
|
||||
auto data_hash = SimpleEncryption::combine_secrets(data, secret);
|
||||
auto data_hash = SimpleEncryption::combine_secrets(salt, data);
|
||||
auto msg_key = data_hash.as_slice().substr(0, 16);
|
||||
|
||||
td::SecureString res_buf(data.size() + 16, 0);
|
||||
|
|
|
@ -43,14 +43,27 @@ class SimpleEncryption {
|
|||
|
||||
class SimpleEncryptionV2 {
|
||||
public:
|
||||
static td::Result<td::SecureString> encrypt_data(td::Slice data, const td::Ed25519::PublicKey &public_key);
|
||||
static td::Result<td::SecureString> decrypt_data(td::Slice data, const td::Ed25519::PrivateKey &private_key);
|
||||
static td::Result<td::SecureString> encrypt_data(td::Slice data, const td::Ed25519::PublicKey &public_key,
|
||||
const td::Ed25519::PrivateKey &private_key);
|
||||
static td::SecureString encrypt_data(td::Slice data, td::Slice secret);
|
||||
static td::Result<td::SecureString> decrypt_data(td::Slice encrypted_data, td::Slice secret);
|
||||
td::Slice salt = {});
|
||||
struct Decrypted {
|
||||
td::SecureString proof;
|
||||
td::SecureString data;
|
||||
};
|
||||
|
||||
static td::Result<Decrypted> decrypt_data(td::Slice data, const td::Ed25519::PrivateKey &private_key,
|
||||
td::Slice sallt = {});
|
||||
static td::Result<td::SecureString> encrypt_data(td::Slice data, const td::Ed25519::PublicKey &public_key,
|
||||
const td::Ed25519::PrivateKey &private_key, td::Slice salt = {});
|
||||
|
||||
static td::Result<td::SecureString> decrypt_data_with_proof(td::Slice encrypted_data, td::Slice proof,
|
||||
td::Slice salt = {});
|
||||
|
||||
static td::SecureString encrypt_data(td::Slice data, td::Slice secret, td::Slice salt = {});
|
||||
static td::Result<Decrypted> decrypt_data(td::Slice encrypted_data, td::Slice secret, td::Slice salt = {});
|
||||
|
||||
private:
|
||||
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret);
|
||||
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret, td::Slice salt = {});
|
||||
static td::Result<td::SecureString> do_decrypt(td::Slice cbc_state_secret, td::Slice msg_key,
|
||||
td::Slice encrypted_data, td::Slice salt);
|
||||
};
|
||||
} // namespace tonlib
|
||||
|
|
|
@ -1384,10 +1384,10 @@ class TonlibCli : public td::actor::Actor {
|
|||
sb << "-" << Grams{td::uint64(-balance)};
|
||||
}
|
||||
sb << " Fee: " << Grams{td::uint64(t->fee_)};
|
||||
if (t->in_msg_->source_.empty()) {
|
||||
if (!t->in_msg_->source_->account_address_.empty()) {
|
||||
sb << " External ";
|
||||
} else {
|
||||
sb << " From " << t->in_msg_->source_;
|
||||
sb << " From " << t->in_msg_->source_->account_address_;
|
||||
}
|
||||
auto print_msg_data = [](td::StringBuilder& sb,
|
||||
tonlib_api::object_ptr<tonlib_api::msg_Data>& msg_data) {
|
||||
|
@ -1406,10 +1406,10 @@ class TonlibCli : public td::actor::Actor {
|
|||
print_msg_data(sb, t->in_msg_->msg_data_);
|
||||
for (auto& ot : t->out_msgs_) {
|
||||
sb << "\n\t";
|
||||
if (ot->destination_.empty()) {
|
||||
if (ot->destination_->account_address_.empty()) {
|
||||
sb << " External ";
|
||||
} else {
|
||||
sb << " To " << ot->destination_;
|
||||
sb << " To " << ot->destination_->account_address_;
|
||||
}
|
||||
sb << " " << Grams{td::uint64(ot->value_)};
|
||||
print_msg_data(sb, ot->msg_data_);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue