aboutsummaryrefslogtreecommitdiffhomepage
path: root/tde2e/td/e2e/Keys.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tde2e/td/e2e/Keys.cpp')
-rw-r--r--tde2e/td/e2e/Keys.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/tde2e/td/e2e/Keys.cpp b/tde2e/td/e2e/Keys.cpp
new file mode 100644
index 000000000..e7aafd289
--- /dev/null
+++ b/tde2e/td/e2e/Keys.cpp
@@ -0,0 +1,208 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include "td/e2e/Keys.h"
+
+#include "td/e2e/MessageEncryption.h"
+
+#include "td/utils/Ed25519.h"
+#include "td/utils/misc.h"
+#include "td/utils/SliceBuilder.h"
+
+namespace tde2e_core {
+
+struct PublicKeyRaw {
+ td::Ed25519::PublicKey public_key;
+};
+
+struct PrivateKeyRaw {
+ PublicKeyRaw public_key;
+ td::Ed25519::PrivateKey private_key;
+ std::shared_ptr<const td::Ed25519::PreparedPrivateKey> prepared_private_key;
+};
+
+struct PrivateKeyWithMnemonicRaw {
+ std::vector<td::SecureString> mnemonic;
+ PrivateKeyRaw key_pair;
+};
+
+Signature Signature::from_u512(const td::UInt512 &signature) {
+ return Signature{signature};
+}
+
+td::UInt512 Signature::to_u512() const {
+ return signature_;
+}
+
+td::Result<Signature> Signature::from_slice(const td::Slice &slice) {
+ td::UInt512 signature;
+ if (slice.size() != 64) {
+ return td::Status::Error(PSLICE() << "Invalid signature length: " << slice.size());
+ }
+ signature.as_mutable_slice().copy_from(slice);
+ return Signature{signature};
+}
+
+td::Slice Signature::to_slice() const {
+ return signature_.as_slice();
+}
+
+auto empty_public_key() {
+ static auto pk = PublicKey::from_u256({});
+ return pk;
+}
+
+PublicKey::PublicKey() : raw_(empty_public_key().raw_) {
+}
+
+PublicKey::PublicKey(std::shared_ptr<const PublicKeyRaw> public_key) : raw_(std::move(public_key)) {
+ CHECK(raw_);
+}
+
+td::Result<PublicKey> PublicKey::from_slice(td::Slice slice) {
+ if (slice.size() != td::Ed25519::PublicKey::LENGTH) {
+ return td::Status::Error("Invalid length of public key");
+ }
+ PublicKeyRaw public_key_raw{td::Ed25519::PublicKey(td::SecureString(slice))};
+ return PublicKey(std::make_shared<PublicKeyRaw>(std::move(public_key_raw)));
+}
+
+PublicKey PublicKey::from_u256(const td::UInt256 &public_key) {
+ PublicKeyRaw public_key_raw{td::Ed25519::PublicKey(td::SecureString(public_key.as_slice()))};
+ return PublicKey(std::make_shared<PublicKeyRaw>(std::move(public_key_raw)));
+}
+
+td::UInt256 PublicKey::to_u256() const {
+ CHECK(raw_);
+ td::UInt256 result;
+ result.as_mutable_slice().copy_from(raw_->public_key.as_octet_string());
+ return result;
+}
+
+td::Status PublicKey::verify(td::Slice data, const Signature &signature) const {
+ CHECK(raw_);
+ return raw_->public_key.verify_signature(data, signature.to_slice());
+}
+
+td::SecureString PublicKey::to_secure_string() const {
+ return raw_->public_key.as_octet_string();
+}
+
+bool PublicKey::operator==(const PublicKey &other) const {
+ return to_u256() == other.to_u256();
+}
+
+bool PublicKey::operator!=(const PublicKey &other) const {
+ return !(*this == other);
+}
+
+bool PublicKey::operator<(const PublicKey &other) const {
+ return to_u256() < other.to_u256();
+}
+
+auto empty_private_key() {
+ static auto pk = PrivateKey::from_slice(std::string(32, 1)).move_as_ok();
+ return pk;
+}
+
+PrivateKey::PrivateKey() : raw_(empty_private_key().raw_) {
+}
+
+PrivateKey::PrivateKey(std::shared_ptr<const PrivateKeyRaw> key_pair) : raw_(std::move(key_pair)) {
+ CHECK(raw_);
+}
+
+td::Result<PrivateKey> PrivateKey::generate() {
+ TRY_RESULT(private_key, td::Ed25519::generate_private_key());
+ TRY_RESULT(public_key, private_key.get_public_key());
+ TRY_RESULT(prepared_private_key, private_key.prepare());
+ return std::make_shared<PrivateKeyRaw>(
+ PrivateKeyRaw{{std::move(public_key)}, std::move(private_key), std::move(prepared_private_key)});
+}
+
+td::Result<PrivateKey> PrivateKey::from_slice(const td::Slice &slice) {
+ if (slice.size() != td::Ed25519::PublicKey::LENGTH) {
+ return td::Status::Error("Invalid private key length");
+ }
+ auto private_key = td::Ed25519::PrivateKey(td::SecureString(slice));
+ TRY_RESULT(public_key, private_key.get_public_key());
+ TRY_RESULT(prepared_private_key, private_key.prepare());
+ return std::make_shared<PrivateKeyRaw>(
+ PrivateKeyRaw{{std::move(public_key)}, std::move(private_key), std::move(prepared_private_key)});
+}
+
+td::Result<td::SecureString> PrivateKey::compute_shared_secret(const PublicKey &public_key) const {
+ TRY_RESULT(x25519_shared_secret, td::Ed25519::compute_shared_secret(public_key.raw().public_key, raw_->private_key));
+ return td::SecureString(
+ MessageEncryption::hmac_sha512("tde2e_shared_secret", x25519_shared_secret).as_slice().substr(0, 32));
+}
+
+td::Result<Signature> PrivateKey::sign(const td::Slice &data) const {
+ CHECK(raw_);
+ TRY_RESULT(signature, td::Ed25519::PrivateKey::sign(*raw_->prepared_private_key, data));
+ //TRY_RESULT(signature, raw_->private_key.sign(data));
+ return Signature::from_slice(signature);
+}
+
+PublicKey PrivateKey::to_public_key() const {
+ CHECK(raw_);
+ return PublicKey(std::shared_ptr<const PublicKeyRaw>(raw_, &raw_->public_key));
+}
+
+td::SecureString PrivateKey::to_secure_string() const {
+ return raw_->private_key.as_octet_string();
+}
+
+PrivateKeyWithMnemonic::PrivateKeyWithMnemonic(std::shared_ptr<const PrivateKeyWithMnemonicRaw> raw)
+ : raw_(std::move(raw)) {
+ CHECK(raw_);
+}
+
+PrivateKeyWithMnemonic PrivateKeyWithMnemonic::from_private_key(const PrivateKey &private_key,
+ std::vector<td::SecureString> words) {
+ return PrivateKeyWithMnemonic(std::make_shared<PrivateKeyWithMnemonicRaw>(PrivateKeyWithMnemonicRaw{
+ std::move(words),
+ PrivateKeyRaw{{td::Ed25519::PublicKey(td::SecureString(private_key.to_public_key().to_u256().as_slice()))},
+ td::Ed25519::PrivateKey(private_key.to_secure_string()),
+ private_key.raw().prepared_private_key}}));
+}
+
+PrivateKey PrivateKeyWithMnemonic::to_private_key() const {
+ return PrivateKey(std::shared_ptr<const PrivateKeyRaw>(raw_, &raw_->key_pair));
+}
+
+td::Span<td::SecureString> PrivateKeyWithMnemonic::words() const {
+ CHECK(raw_);
+ return raw_->mnemonic;
+}
+
+PublicKey PrivateKeyWithMnemonic::to_public_key() const {
+ return to_private_key().to_public_key();
+}
+
+td::Result<Signature> PrivateKeyWithMnemonic::sign(const td::Slice &data) const {
+ return to_private_key().sign(data);
+}
+
+td::StringBuilder &operator<<(td::StringBuilder &sb, const PrivateKeyWithMnemonic &key_pair_with_mnemonic) {
+ return sb << "EdPrivateKey(pub="
+ << td::hex_encode(key_pair_with_mnemonic.to_public_key().to_u256().as_slice().substr(0, 8)) << "...)";
+}
+
+td::StringBuilder &operator<<(td::StringBuilder &sb, const PrivateKey &key_pair) {
+ return sb << "EdPrivateKey(pub=" << td::hex_encode(key_pair.to_public_key().to_u256().as_slice().substr(0, 8))
+ << "...)";
+}
+
+td::StringBuilder &operator<<(td::StringBuilder &sb, const PublicKey &public_key) {
+ return sb << "EdPublicKey(" << td::hex_encode(public_key.to_u256().as_slice().substr(0, 8)) << "...)";
+}
+
+td::StringBuilder &operator<<(td::StringBuilder &sb, const Signature &signature) {
+ return sb << "Signature(" << td::hex_encode(signature.signature_.as_slice().substr(0, 8)) << "...)";
+}
+
+} // namespace tde2e_core