mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated tonlib
This commit is contained in:
parent
dd745485e2
commit
7c595294b6
12 changed files with 125 additions and 14 deletions
|
@ -39,6 +39,34 @@
|
|||
// { dup abs <# #s rot sign #> nip } : (.)
|
||||
// { (.) type } : ._
|
||||
// { ._ space } : .
|
||||
{ dup 10 < { 48 } { 55 } cond + } : Digit
|
||||
{ dup 10 < { 48 } { 87 } cond + } : digit
|
||||
// x s b -- x' s'
|
||||
{ -rot swap rot /mod Digit rot swap hold } : B#
|
||||
{ -rot swap rot /mod digit rot swap hold } : b#
|
||||
{ 16 B# } : X#
|
||||
{ 16 b# } : x#
|
||||
// x s b -- 0 s'
|
||||
{ -rot { 2 pick B# over 0<= } until rot drop } : B#s
|
||||
{ -rot { 2 pick b# over 0<= } until rot drop } : b#s
|
||||
{ 16 B#s } : X#s
|
||||
{ 16 b#s } : x#s
|
||||
variable base
|
||||
{ 10 base ! } : decimal
|
||||
{ 16 base ! } : hex
|
||||
{ 8 base ! } : octal
|
||||
{ 2 base ! } : binary
|
||||
{ base @ B# } : Base#
|
||||
{ base @ b# } : base#
|
||||
{ base @ B#s } : Base#s
|
||||
{ base @ b#s } : base#s
|
||||
// x w -- s
|
||||
{ over abs <# rot 1- ' X# swap times X#s rot sign #> nip } : (0X.)
|
||||
{ over abs <# rot 1- ' x# swap times x#s rot sign #> nip } : (0x.)
|
||||
{ (0X.) type } : 0X._
|
||||
{ 0X._ space } : 0X.
|
||||
{ (0x.) type } : 0x._
|
||||
{ 0x._ space } : 0x.
|
||||
{ bl (-trailing) } : -trailing
|
||||
{ char 0 (-trailing) } : -trailing0
|
||||
{ char " word 1 ' $+ } ::_ +"
|
||||
|
|
|
@ -33,7 +33,7 @@ library TonUtil // TON Blockchain Fift Library
|
|||
} : parse-smc-addr
|
||||
|
||||
// ( wc addr -- ) Show address in <workchain>:<account> form
|
||||
{ swap ._ .":" x. } : .addr
|
||||
{ swap ._ .":" 64 0x. } : .addr
|
||||
// ( wc addr flags -- ) Show address in base64url form
|
||||
{ smca>$ type } : .Addr
|
||||
// ( wc addr fname -- ) Save address to file in 36-byte format
|
||||
|
|
|
@ -85,6 +85,8 @@ logVerbosityLevel verbosity_level:int32 = LogVerbosityLevel;
|
|||
//@description Contains a list of available TDLib internal log tags @tags List of log tags
|
||||
logTags tags:vector<string> = LogTags;
|
||||
|
||||
data bytes:secureBytes = Data;
|
||||
|
||||
---functions---
|
||||
|
||||
init options:options = Ok;
|
||||
|
@ -103,6 +105,10 @@ importPemKey local_password:secureBytes key_password:secureBytes exported_key:ex
|
|||
importEncryptedKey local_password:secureBytes key_password:secureBytes exported_encrypted_key:exportedEncryptedKey = Key;
|
||||
changeLocalPassword input_key:inputKey new_local_password:secureBytes = Key;
|
||||
|
||||
encrypt decrypted_data:secureBytes secret:secureBytes = Data;
|
||||
decrypt encrypted_data:secureBytes secret:secureBytes = Data;
|
||||
kdf password:secureBytes salt:secureBytes iterations:int32 = Data;
|
||||
|
||||
unpackAccountAddress account_address:string = UnpackedAccountAddress;
|
||||
packAccountAddress account_address:unpackedAccountAddress = AccountAddress;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -430,6 +430,34 @@ TEST(Tonlib, ParseAddres) {
|
|||
ASSERT_EQ("Uf9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfdyS", addr_str2->account_address_);
|
||||
}
|
||||
|
||||
TEST(Tonlib, EncryptionApi) {
|
||||
using tonlib_api::make_object;
|
||||
Client client;
|
||||
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(
|
||||
make_object<tonlib_api::options>(nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("."))))
|
||||
.ensure();
|
||||
|
||||
std::string password = "hello world";
|
||||
std::string data = "very secret data";
|
||||
auto key = std::move(
|
||||
sync_send(client, make_object<tonlib_api::kdf>(td::SecureString(password), td::SecureString("salt"), 100000))
|
||||
.move_as_ok()
|
||||
->bytes_);
|
||||
auto encrypted = std::move(
|
||||
sync_send(client, make_object<tonlib_api::encrypt>(td::SecureString(data), key.copy())).move_as_ok()->bytes_);
|
||||
auto decrypted =
|
||||
std::move(sync_send(client, make_object<tonlib_api::decrypt>(encrypted.copy(), key.copy())).move_as_ok()->bytes_);
|
||||
ASSERT_EQ(data, decrypted);
|
||||
|
||||
auto bad_key = std::move(sync_send(client, make_object<tonlib_api::kdf>(td::SecureString(password + "BAD"),
|
||||
td::SecureString("salt"), 100000))
|
||||
.move_as_ok()
|
||||
->bytes_);
|
||||
sync_send(client, make_object<tonlib_api::decrypt>(encrypted.copy(), bad_key.copy())).ensure_error();
|
||||
}
|
||||
|
||||
TEST(Tonlib, KeysApi) {
|
||||
using tonlib_api::make_object;
|
||||
Client client;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "tonlib/TestGiver.h"
|
||||
#include "tonlib/utils.h"
|
||||
#include "tonlib/keys/Mnemonic.h"
|
||||
#include "tonlib/keys/SimpleEncryption.h"
|
||||
|
||||
#include "tonlib/TonlibError.h"
|
||||
|
||||
|
@ -444,7 +445,7 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::static_request(
|
|||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> response;
|
||||
downcast_call(*function, [&response](auto& request) { response = TonlibClient::do_static_request(request); });
|
||||
VLOG(tonlib_query) << " answer static query " << to_string(function);
|
||||
VLOG(tonlib_query) << " answer static query " << to_string(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -466,6 +467,9 @@ bool TonlibClient::is_static_request(td::int32 id) {
|
|||
case tonlib_api::setLogTagVerbosityLevel::ID:
|
||||
case tonlib_api::getLogTagVerbosityLevel::ID:
|
||||
case tonlib_api::addLogMessage::ID:
|
||||
case tonlib_api::encrypt::ID:
|
||||
case tonlib_api::decrypt::ID:
|
||||
case tonlib_api::kdf::ID:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -1633,4 +1637,28 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const
|
|||
return tonlib_api::make_object<tonlib_api::ok>();
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const tonlib_api::encrypt& request) {
|
||||
return tonlib_api::make_object<tonlib_api::data>(
|
||||
SimpleEncryption::encrypt_data(request.decrypted_data_, request.secret_));
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const tonlib_api::decrypt& request) {
|
||||
auto r_data = SimpleEncryption::decrypt_data(request.encrypted_data_, request.secret_);
|
||||
if (r_data.is_ok()) {
|
||||
return tonlib_api::make_object<tonlib_api::data>(r_data.move_as_ok());
|
||||
} else {
|
||||
return status_to_tonlib_api(r_data.error().move_as_error_prefix(TonlibError::KeyDecrypt()));
|
||||
}
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const tonlib_api::kdf& request) {
|
||||
auto max_iterations = 10000000;
|
||||
if (request.iterations_ < 0 || request.iterations_ > max_iterations) {
|
||||
return status_to_tonlib_api(
|
||||
TonlibError::InvalidField("iterations", PSLICE() << "must be between 0 and " << max_iterations));
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::data>(
|
||||
SimpleEncryption::kdf(request.password_, request.salt_, request.iterations_));
|
||||
}
|
||||
|
||||
} // namespace tonlib
|
||||
|
|
|
@ -117,6 +117,10 @@ class TonlibClient : public td::actor::Actor {
|
|||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::getLogTags& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::addLogMessage& request);
|
||||
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::encrypt& request);
|
||||
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);
|
||||
|
||||
template <class T, class P>
|
||||
td::Status do_request(const T& request, P&& promise) {
|
||||
return td::Status::Error(400, "Function is unsupported");
|
||||
|
|
|
@ -42,12 +42,10 @@ EncryptedKey DecryptedKey::encrypt(td::Slice local_password, td::Slice old_secre
|
|||
} else {
|
||||
td::Random::secure_bytes(secret.as_mutable_slice());
|
||||
}
|
||||
td::SecureString decrypted_secret(32);
|
||||
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||
td::SecureString decrypted_secret = SimpleEncryption::combine_secrets(secret, local_password);
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS,
|
||||
encryption_secret.as_mutable_slice());
|
||||
td::SecureString encryption_secret =
|
||||
SimpleEncryption::kdf(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS);
|
||||
|
||||
std::vector<td::SecureString> mnemonic_words_copy;
|
||||
for (auto &w : mnemonic_words) {
|
||||
|
|
|
@ -28,19 +28,21 @@ td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool ch
|
|||
if (secret.size() != 32) {
|
||||
return td::Status::Error("Failed to decrypt key: invalid secret size");
|
||||
}
|
||||
td::SecureString decrypted_secret(32);
|
||||
td::SecureString decrypted_secret;
|
||||
if (old) {
|
||||
decrypted_secret = td::SecureString(32);
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
} else {
|
||||
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||
decrypted_secret = SimpleEncryption::combine_secrets(secret, local_password);
|
||||
}
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", PBKDF_ITERATIONS, encryption_secret.as_mutable_slice());
|
||||
td::SecureString encryption_secret =
|
||||
SimpleEncryption::kdf(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS);
|
||||
|
||||
TRY_RESULT(decrypted_data, SimpleEncryption::decrypt_data(as_slice(encrypted_data), as_slice(encryption_secret)));
|
||||
|
||||
RawDecryptedKey raw_decrypted_key;
|
||||
|
|
|
@ -50,6 +50,12 @@ td::SecureString SimpleEncryption::combine_secrets(td::Slice a, td::Slice b) {
|
|||
return res;
|
||||
}
|
||||
|
||||
td::SecureString SimpleEncryption::kdf(td::Slice secret, td::Slice password, int iterations) {
|
||||
td::SecureString new_secret(64);
|
||||
pbkdf2_sha512(secret, password, iterations, new_secret.as_mutable_slice());
|
||||
return new_secret;
|
||||
}
|
||||
|
||||
td::SecureString SimpleEncryption::encrypt_data_with_prefix(td::Slice data, td::Slice secret) {
|
||||
CHECK(data.size() % 16 == 0);
|
||||
auto data_hash = sha256(data);
|
||||
|
|
|
@ -27,13 +27,14 @@ class SimpleEncryption {
|
|||
public:
|
||||
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);
|
||||
static td::SecureString combine_secrets(td::Slice a, td::Slice b);
|
||||
static td::SecureString kdf(td::Slice secret, td::Slice password, int iterations);
|
||||
|
||||
private:
|
||||
static td::AesCbcState calc_aes_cbc_state_hash(td::Slice hash);
|
||||
static td::AesCbcState calc_aes_cbc_state_sha512(td::Slice seed);
|
||||
static td::SecureString gen_random_prefix(td::int64 data_size);
|
||||
|
||||
static td::SecureString combine_secrets(td::Slice a, td::Slice b);
|
||||
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret);
|
||||
};
|
||||
} // namespace tonlib
|
||||
|
|
|
@ -58,6 +58,9 @@ class TonlibCli : public td::actor::Actor {
|
|||
bool is_closing_{false};
|
||||
td::uint32 ref_cnt_{1};
|
||||
|
||||
td::int64 snd_bytes_{0};
|
||||
td::int64 rcv_bytes_{0};
|
||||
|
||||
void start_up() override {
|
||||
class Cb : public td::TerminalIO::Callback {
|
||||
public:
|
||||
|
@ -258,15 +261,21 @@ class TonlibCli : public td::actor::Actor {
|
|||
auto addr = parser.read_word();
|
||||
auto bounceable = parser.read_word();
|
||||
set_bounceable(addr, to_bool(bounceable, true));
|
||||
} else if (cmd == "netstats") {
|
||||
dump_netstats();
|
||||
}
|
||||
}
|
||||
|
||||
void dump_netstats() {
|
||||
td::TerminalIO::out() << td::tag("snd", td::format::as_size(snd_bytes_)) << "\n";
|
||||
td::TerminalIO::out() << td::tag("rcv", td::format::as_size(rcv_bytes_)) << "\n";
|
||||
}
|
||||
void on_adnl_result(td::uint64 id, td::Result<td::BufferSlice> res) {
|
||||
using tonlib_api::make_object;
|
||||
if (res.is_ok()) {
|
||||
rcv_bytes_ += res.ok().size();
|
||||
send_query(make_object<tonlib_api::onLiteServerQueryResult>(id, res.move_as_ok().as_slice().str()),
|
||||
[](auto r_ok) { LOG_IF(ERROR, r_ok.is_error()) << r_ok.error(); });
|
||||
LOG(ERROR) << "!!!";
|
||||
} else {
|
||||
send_query(make_object<tonlib_api::onLiteServerQueryError>(
|
||||
id, make_object<tonlib_api::error>(res.error().code(), res.error().message().str())),
|
||||
|
@ -279,6 +288,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
if (result->get_id() == tonlib_api::updateSendLiteServerQuery::ID) {
|
||||
auto update = tonlib_api::move_object_as<tonlib_api::updateSendLiteServerQuery>(std::move(result));
|
||||
CHECK(!raw_client_.empty());
|
||||
snd_bytes_ += update->data_.size();
|
||||
send_closure(raw_client_, &ton::adnl::AdnlExtClient::send_query, "query", td::BufferSlice(update->data_),
|
||||
td::Timestamp::in(5),
|
||||
[actor_id = actor_id(this), id = update->id_](td::Result<td::BufferSlice> res) {
|
||||
|
@ -800,7 +810,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
}
|
||||
void transfer(Address from, Address to, td::uint64 grams, td::Slice password, td::Slice message,
|
||||
bool allow_send_to_uninited) {
|
||||
auto r_sz = td::to_integer_safe<td::size_t>(message);
|
||||
auto r_sz = td::to_integer_safe<size_t>(message);
|
||||
auto msg = message.str();
|
||||
if (r_sz.is_ok()) {
|
||||
msg = std::string(r_sz.ok(), 'Z');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue