diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 6f7ef8f0..d9c90f51 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -777,6 +777,9 @@ namespace client m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { + 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 (); // extract encryption type params for LS2 if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 && params) @@ -1048,9 +1051,7 @@ namespace client // standard LS2 (type 3) assumed for now. TODO: implement others auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256; leaseSet = new i2p::data::LocalLeaseSet2 (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, - GetIdentity (), m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels); - // sign - Sign (leaseSet->GetBuffer () - 1, leaseSet->GetBufferLen () - leaseSet->GetSignatureLen () + 1, leaseSet->GetSignature ()); // + leading store type + m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels); } SetLeaseSet (leaseSet); } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 847ecb1a..5c141236 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -126,6 +126,7 @@ namespace client void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); int GetLeaseSetType () const { return m_LeaseSetType; }; + void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; virtual void CleanupDestination () {}; // additional clean up in derived classes // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 476038cd..9f90222f 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -163,7 +163,9 @@ namespace data static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub); static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long + // offline keys PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const; + const std::vector GetOfflineSignature () const { return m_OfflineSignature; }; private: diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d384f350..b9af03b7 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -285,7 +285,7 @@ namespace data uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags - if (flags & 0x0001) + if (flags & LEASESET2_FLAG_OFFLINE_KEYS) { // transient key m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset); @@ -431,7 +431,7 @@ namespace data uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags - if (flags & 0x0001) + if (flags & LEASESET2_FLAG_OFFLINE_KEYS) { // transient key m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset); @@ -579,16 +579,24 @@ namespace data return ident.Verify(ptr, leases - ptr, leases); } - LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, + LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, std::vector > tunnels): - LocalLeaseSet (identity, nullptr, 0) + LocalLeaseSet (keys.GetPublic (), nullptr, 0) { + auto identity = keys.GetPublic (); // assume standard LS2 int num = tunnels.size (); if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ + 1/*num keys*/ + 2/*key type*/ + 2/*key len*/ + keyLen/*key*/ + 1/*num leases*/ + num*LEASE2_SIZE + identity->GetSignatureLen (); + uint16_t flags = 0; + if (keys.IsOfflineSignature ()) + { + flags |= LEASESET2_FLAG_OFFLINE_KEYS; + m_BufferLen += keys.GetOfflineSignature ().size (); + } + m_Buffer = new uint8_t[m_BufferLen + 1]; m_Buffer[0] = storeType; // LS2 header @@ -597,6 +605,13 @@ namespace data htobe32buf (m_Buffer + offset, timestamp); offset += 4; // published timestamp (seconds) uint8_t * expiresBuf = m_Buffer + offset; offset += 2; // expires, fill later htobe16buf (m_Buffer + offset, 0); offset += 2; // flags + if (keys.IsOfflineSignature ()) + { + // offline signature + const auto& offlineSignature = keys.GetOfflineSignature (); + memcpy (m_Buffer + offset, offlineSignature.data (), offlineSignature.size ()); + offset += offlineSignature.size (); + } htobe16buf (m_Buffer + offset, 0); offset += 2; // properties len // keys m_Buffer[offset] = 1; offset++; // 1 key @@ -621,7 +636,8 @@ namespace data SetExpirationTime (expirationTime*1000LL); auto expires = expirationTime - timestamp; htobe16buf (expiresBuf, expires > 0 ? expires : 0); - // we don't sign it yet. must be signed later on + // sign + keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type } LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len): diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index fbe3d7e4..44ee873c 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -124,6 +124,9 @@ namespace data const uint8_t NETDB_STORE_TYPE_STANDARD_LEASESET2 = 3; const uint8_t NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 = 5; const uint8_t NETDB_STORE_TYPE_META_LEASESET2 = 7; + + const uint16_t LEASESET2_FLAG_OFFLINE_KEYS = 0x0001; + class LeaseSet2: public LeaseSet { public: @@ -211,7 +214,7 @@ namespace data { public: - LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, + LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, std::vector > tunnels); LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len);