mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-08-26 12:51:54 +00:00
handle multiple ECIESx25519 encryption keys
This commit is contained in:
parent
edc27d5bcb
commit
3a18e7ab91
@ -28,8 +28,7 @@ namespace client
|
|||||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, bool isSameThread,
|
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, bool isSameThread,
|
||||||
const std::map<std::string, std::string>& params):
|
const std::map<std::string, std::string>& params):
|
||||||
LeaseSetDestination (service, isPublic, ¶ms),
|
LeaseSetDestination (service, isPublic, ¶ms),
|
||||||
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()),
|
m_Owner (owner), m_Identity (identity), m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread),
|
||||||
m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread),
|
|
||||||
m_LeaseSetCreationTimer (service), m_ReadinessCheckTimer (service)
|
m_LeaseSetCreationTimer (service), m_ReadinessCheckTimer (service)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -42,26 +41,59 @@ namespace client
|
|||||||
m_Owner = nullptr;
|
m_Owner = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
void I2CPDestination::SetEncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key)
|
||||||
{
|
{
|
||||||
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key);
|
bool exist = false;
|
||||||
|
auto it = m_EncryptionKeys.find (keyType);
|
||||||
|
if (it != m_EncryptionKeys.end () && !memcmp (it->second->priv.data (), key, it->second->priv.size ())) // new key?
|
||||||
|
exist = true;
|
||||||
|
if (!exist)
|
||||||
|
{
|
||||||
|
auto encryptionKey = std::make_shared<i2p::crypto::LocalEncryptionKey> (keyType);
|
||||||
|
memcpy (encryptionKey->priv.data (), key, encryptionKey->priv.size ());
|
||||||
|
encryptionKey->CreateDecryptor (); // from private key
|
||||||
|
m_EncryptionKeys.insert_or_assign (keyType, encryptionKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPDestination::SetECIESx25519EncryptionPrivateKey (const uint8_t * key)
|
void I2CPDestination::SetECIESx25519EncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key)
|
||||||
{
|
{
|
||||||
if (!m_ECIESx25519Decryptor || memcmp (m_ECIESx25519PrivateKey, key, 32)) // new key?
|
bool exist = false;
|
||||||
|
auto it = m_EncryptionKeys.find (keyType);
|
||||||
|
if (it != m_EncryptionKeys.end () && !memcmp (it->second->priv.data (), key, it->second->priv.size ())) // new key?
|
||||||
|
exist = true;
|
||||||
|
if (!exist)
|
||||||
{
|
{
|
||||||
m_ECIESx25519Decryptor = std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key, true); // calculate public
|
auto encryptionKey = std::make_shared<i2p::crypto::LocalEncryptionKey> (keyType);
|
||||||
memcpy (m_ECIESx25519PrivateKey, key, 32);
|
memcpy (encryptionKey->priv.data (), key, encryptionKey->priv.size ());
|
||||||
|
// create decryptor manually
|
||||||
|
auto decryptor = std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key, true); // calculate publicKey
|
||||||
|
encryptionKey->decryptor = decryptor;
|
||||||
|
// assign public key from decryptor
|
||||||
|
memcpy (encryptionKey->pub.data (), decryptor->GetPubicKey (), encryptionKey->pub.size ());
|
||||||
|
// insert or replace new
|
||||||
|
m_EncryptionKeys.insert_or_assign (keyType, encryptionKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const
|
bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const
|
||||||
{
|
{
|
||||||
if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && m_ECIESx25519Decryptor)
|
std::shared_ptr<i2p::crypto::LocalEncryptionKey> encryptionKey;
|
||||||
return m_ECIESx25519Decryptor->Decrypt (encrypted, data);
|
if (!m_EncryptionKeys.empty ())
|
||||||
if (m_Decryptor)
|
{
|
||||||
return m_Decryptor->Decrypt (encrypted, data);
|
if (m_EncryptionKeys.rbegin ()->first == preferredCrypto)
|
||||||
|
encryptionKey = m_EncryptionKeys.rbegin ()->second;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto it = m_EncryptionKeys.find (preferredCrypto);
|
||||||
|
if (it != m_EncryptionKeys.end ())
|
||||||
|
encryptionKey = it->second;
|
||||||
|
}
|
||||||
|
if (!encryptionKey)
|
||||||
|
encryptionKey = m_EncryptionKeys.rbegin ()->second;
|
||||||
|
}
|
||||||
|
if (encryptionKey)
|
||||||
|
return encryptionKey->decryptor->Decrypt (encrypted, data);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "I2CP: Decryptor is not set");
|
LogPrint (eLogError, "I2CP: Decryptor is not set");
|
||||||
return false;
|
return false;
|
||||||
@ -69,21 +101,31 @@ namespace client
|
|||||||
|
|
||||||
const uint8_t * I2CPDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
|
const uint8_t * I2CPDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
|
||||||
{
|
{
|
||||||
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && m_ECIESx25519Decryptor)
|
auto it = m_EncryptionKeys.find (keyType);
|
||||||
return m_ECIESx25519Decryptor->GetPubicKey ();
|
if (it != m_EncryptionKeys.end ())
|
||||||
|
return it->second->pub.data ();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I2CPDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
|
bool I2CPDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
|
||||||
{
|
{
|
||||||
return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519Decryptor : m_EncryptionKeyType == keyType;
|
#if __cplusplus >= 202002L // C++20
|
||||||
|
return m_EncryptionKeys.contains (keyType);
|
||||||
|
#else
|
||||||
|
return m_EncryptionKeys.count (keyType) > 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::data::CryptoKeyType I2CPDestination::GetPreferredCryptoType () const
|
i2p::data::CryptoKeyType I2CPDestination::GetPreferredCryptoType () const
|
||||||
{
|
{
|
||||||
if (m_ECIESx25519Decryptor)
|
return !m_EncryptionKeys.empty () ? m_EncryptionKeys.rbegin ()->first : 0;
|
||||||
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
|
}
|
||||||
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
|
|
||||||
|
i2p::data::CryptoKeyType I2CPDestination::GetRatchetsHighestCryptoType () const
|
||||||
|
{
|
||||||
|
if (m_EncryptionKeys.empty ()) return 0;
|
||||||
|
auto cryptoType = m_EncryptionKeys.rbegin ()->first;
|
||||||
|
return cryptoType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? cryptoType : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len,
|
void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len,
|
||||||
@ -813,7 +855,7 @@ namespace client
|
|||||||
// we always assume this field as 20 bytes (DSA) regardless actual size
|
// we always assume this field as 20 bytes (DSA) regardless actual size
|
||||||
// instead of
|
// instead of
|
||||||
//offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen ();
|
//offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen ();
|
||||||
m_Destination->SetEncryptionPrivateKey (buf + offset);
|
m_Destination->SetEncryptionPrivateKey (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, buf + offset);
|
||||||
offset += 256;
|
offset += 256;
|
||||||
m_Destination->LeaseSetCreated (buf + offset, len - offset);
|
m_Destination->LeaseSetCreated (buf + offset, len - offset);
|
||||||
}
|
}
|
||||||
@ -846,13 +888,10 @@ namespace client
|
|||||||
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type
|
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type
|
||||||
uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length
|
uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length
|
||||||
if (offset + keyLen > len) return;
|
if (offset + keyLen > len) return;
|
||||||
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
if (keyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||||
m_Destination->SetECIESx25519EncryptionPrivateKey (buf + offset);
|
m_Destination->SetECIESx25519EncryptionPrivateKey (keyType, buf + offset);
|
||||||
else
|
else
|
||||||
{
|
m_Destination->SetEncryptionPrivateKey (keyType, buf + offset); // from identity
|
||||||
m_Destination->SetEncryptionType (keyType);
|
|
||||||
m_Destination->SetEncryptionPrivateKey (buf + offset);
|
|
||||||
}
|
|
||||||
offset += keyLen;
|
offset += keyLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +92,8 @@ namespace client
|
|||||||
|
|
||||||
void Stop () override;
|
void Stop () override;
|
||||||
|
|
||||||
void SetEncryptionPrivateKey (const uint8_t * key);
|
void SetEncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key);
|
||||||
void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
|
void SetECIESx25519EncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key);
|
||||||
void SetECIESx25519EncryptionPrivateKey (const uint8_t * key);
|
|
||||||
void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession
|
void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession
|
||||||
void LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len); // called from I2CPSession
|
void LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len); // called from I2CPSession
|
||||||
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
|
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
|
||||||
@ -109,10 +108,7 @@ namespace client
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
// GarlicDestination
|
// GarlicDestination
|
||||||
i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override
|
i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override;
|
||||||
{
|
|
||||||
return m_ECIESx25519Decryptor ? i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD : 0;
|
|
||||||
}
|
|
||||||
// LeaseSetDestination
|
// LeaseSetDestination
|
||||||
void CleanupDestination () override;
|
void CleanupDestination () override;
|
||||||
i2p::data::CryptoKeyType GetPreferredCryptoType () const override;
|
i2p::data::CryptoKeyType GetPreferredCryptoType () const override;
|
||||||
@ -134,10 +130,7 @@ namespace client
|
|||||||
|
|
||||||
std::shared_ptr<I2CPSession> m_Owner;
|
std::shared_ptr<I2CPSession> m_Owner;
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> m_Identity;
|
std::shared_ptr<const i2p::data::IdentityEx> m_Identity;
|
||||||
i2p::data::CryptoKeyType m_EncryptionKeyType;
|
std::map<i2p::data::CryptoKeyType, std::shared_ptr<i2p::crypto::LocalEncryptionKey> > m_EncryptionKeys; // last is most preferable
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor; // standard
|
|
||||||
std::shared_ptr<i2p::crypto::ECIESX25519AEADRatchetDecryptor> m_ECIESx25519Decryptor;
|
|
||||||
uint8_t m_ECIESx25519PrivateKey[32];
|
|
||||||
uint64_t m_LeaseSetExpirationTime;
|
uint64_t m_LeaseSetExpirationTime;
|
||||||
bool m_IsCreatingLeaseSet, m_IsSameThread;
|
bool m_IsCreatingLeaseSet, m_IsSameThread;
|
||||||
boost::asio::deadline_timer m_LeaseSetCreationTimer, m_ReadinessCheckTimer;
|
boost::asio::deadline_timer m_LeaseSetCreationTimer, m_ReadinessCheckTimer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user