1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

emergency update

This commit is contained in:
ton 2020-03-24 03:32:16 +04:00
parent 5d846e0aaf
commit 9f351fc29f
87 changed files with 2486 additions and 655 deletions

View file

@ -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); }));
}

View file

@ -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_));
}

View file

@ -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

View file

@ -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_;

View file

@ -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);

View file

@ -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

View file

@ -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_);