From d923f0e01bdb2f90689e7153a36479fe0ac4af26 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Apr 2020 19:12:44 -0400 Subject: [PATCH] support two encryption keys --- libi2pd/Destination.cpp | 73 ++++++++++++++++++++++++++++------------- libi2pd/Destination.h | 32 ++++++++++-------- 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 796b0438..30648a42 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -839,23 +839,26 @@ namespace client if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only - m_EncryptionKeyType = GetIdentity ()->GetCryptoKeyType (); + auto encryptionKeyType = GetIdentity ()->GetCryptoKeyType (); // extract encryption type params for LS2 if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 && params) { auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE); if (it != params->end ()) - m_EncryptionKeyType = std::stoi(it->second); + encryptionKeyType = std::stoi(it->second); } - memset (m_EncryptionPrivateKey, 0, 256); - memset (m_EncryptionPublicKey, 0, 256); + auto encryptionKey = new EncryptionKey (encryptionKeyType); if (isPublic) - PersistTemporaryKeys (); + PersistTemporaryKeys (encryptionKey); else - i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey); + encryptionKey->GenerateKeys (); + encryptionKey->CreateDecryptor (); + if (encryptionKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) + m_ECIESx25519EncryptionKey.reset (encryptionKey); + else + m_StandardEncryptionKey.reset (encryptionKey); - m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_EncryptionKeyType, m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); @@ -1092,27 +1095,27 @@ namespace client return ret; } - void ClientDestination::PersistTemporaryKeys () + void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys) { std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat")); std::ifstream f(path, std::ifstream::binary); if (f) { - f.read ((char *)m_EncryptionPublicKey, 256); - f.read ((char *)m_EncryptionPrivateKey, 256); + f.read ((char *)keys->pub, 256); + f.read ((char *)keys->priv, 256); return; } LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); - memset (m_EncryptionPrivateKey, 0, 256); - memset (m_EncryptionPublicKey, 0, 256); - i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey); + memset (keys->priv, 0, 256); + memset (keys->pub, 0, 256); + keys->GenerateKeys (); // TODO:: persist crypto key type std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); if (f1) { - f1.write ((char *)m_EncryptionPublicKey, 256); - f1.write ((char *)m_EncryptionPrivateKey, 256); + f1.write ((char *)keys->pub, 256); + f1.write ((char *)keys->priv, 256); return; } LogPrint(eLogError, "Destinations: Can't save keys to ", path); @@ -1123,18 +1126,27 @@ namespace client std::shared_ptr leaseSet; if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) { - leaseSet = std::make_shared (GetIdentity (), m_EncryptionPublicKey, tunnels); - // sign - Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); + if (m_StandardEncryptionKey) + { + leaseSet = std::make_shared (GetIdentity (), m_StandardEncryptionKey->pub, tunnels); + // sign + Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); + } + else + LogPrint (eLogError, "Destinations: Wrong encryption key type for LeaseSet type 1"); } else { // standard LS2 (type 3) first - uint16_t keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256; + i2p::data::LocalLeaseSet2::KeySections keySections; + if (m_ECIESx25519EncryptionKey) + keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} ); + if (m_StandardEncryptionKey) + keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} ); + bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; auto ls2 = std::make_shared (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, - m_Keys, i2p::data::LocalLeaseSet2::KeySections { {m_EncryptionKeyType, keyLen, m_EncryptionPublicKey} }, - tunnels, IsPublic (), isPublishedEncrypted); + m_Keys, keySections, tunnels, IsPublic (), isPublishedEncrypted); if (isPublishedEncrypted) // encrypt if type 5 ls2 = std::make_shared (ls2, m_Keys, GetAuthType (), m_AuthKeys); leaseSet = ls2; @@ -1149,13 +1161,28 @@ namespace client bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const { - if (m_Decryptor) - return m_Decryptor->Decrypt (encrypted, data, ctx, true); + if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) + if (m_ECIESx25519EncryptionKey && m_ECIESx25519EncryptionKey->decryptor) + return m_ECIESx25519EncryptionKey->decryptor->Decrypt (encrypted, data, ctx, true); + if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor) + return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data, ctx, true); else LogPrint (eLogError, "Destinations: decryptor is not set"); return false; } + bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const + { + return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey; + } + + const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const + { + if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) + return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr; + return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr; + } + void ClientDestination::ReadAuthKey (const std::string& group, const std::map * params) { for (auto it: *params) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index c19c3f16..4d51877b 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -1,6 +1,7 @@ #ifndef DESTINATION_H__ #define DESTINATION_H__ +#include #include #include #include @@ -192,6 +193,17 @@ namespace client class ClientDestination: public LeaseSetDestination { + struct EncryptionKey + { + uint8_t pub[256], priv[256]; + i2p::data::CryptoKeyType keyType; + std::shared_ptr decryptor; + + EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); }; + void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); }; + void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); }; + }; + public: ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, @@ -229,13 +241,8 @@ namespace client // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const; std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; - bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const - { - return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? - m_EncryptionKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET : - m_EncryptionKeyType < i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET; - } - const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; }; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; + const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; protected: @@ -249,15 +256,14 @@ namespace client std::shared_ptr GetSharedFromThis () { return std::static_pointer_cast(shared_from_this ()); } - void PersistTemporaryKeys (); + void PersistTemporaryKeys (EncryptionKey * keys); void ReadAuthKey (const std::string& group, const std::map * params); - private: - + private: + i2p::data::PrivateKeys m_Keys; - uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; - i2p::data::CryptoKeyType m_EncryptionKeyType; - std::shared_ptr m_Decryptor; + std::unique_ptr m_StandardEncryptionKey; + std::unique_ptr m_ECIESx25519EncryptionKey; int m_StreamingAckDelay; std::shared_ptr m_StreamingDestination; // default