Skip to content

Commit

Permalink
updated tonlib
Browse files Browse the repository at this point in the history
  • Loading branch information
ton committed Oct 4, 2019
1 parent dd74548 commit 7c59529
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 14 deletions.
28 changes: 28 additions & 0 deletions crypto/fift/lib/Fift.fif
Original file line number Diff line number Diff line change
Expand Up @@ -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 ' $+ } ::_ +"
Expand Down
2 changes: 1 addition & 1 deletion crypto/fift/lib/TonUtil.fif
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions tl/generate/scheme/tonlib_api.tl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
Binary file modified tl/generate/scheme/tonlib_api.tlo
Binary file not shown.
28 changes: 28 additions & 0 deletions tonlib/test/offline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 29 additions & 1 deletion tonlib/tonlib/TonlibClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions tonlib/tonlib/TonlibClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
8 changes: 3 additions & 5 deletions tonlib/tonlib/keys/DecryptedKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
10 changes: 6 additions & 4 deletions tonlib/tonlib/keys/EncryptedKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions tonlib/tonlib/keys/SimpleEncryption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion tonlib/tonlib/keys/SimpleEncryption.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
14 changes: 12 additions & 2 deletions tonlib/tonlib/tonlib-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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())),
Expand All @@ -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) {
Expand Down Expand Up @@ -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');
Expand Down

0 comments on commit 7c59529

Please sign in to comment.