mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-13 04:46:38 +01:00
H and HKDF for encrypted LeaseSet2
This commit is contained in:
parent
2f0115c300
commit
af65af5be9
2 changed files with 66 additions and 9 deletions
|
@ -1,4 +1,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
@ -251,15 +253,21 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases):
|
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases):
|
||||||
LeaseSet (storeLeases), m_StoreType (storeType), m_PublishedTimestamp (0)
|
LeaseSet (storeLeases), m_StoreType (storeType)
|
||||||
{
|
{
|
||||||
SetBuffer (buf, len);
|
SetBuffer (buf, len);
|
||||||
if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
ReadFromBufferEncrypted (buf, len);
|
ReadFromBufferEncrypted (buf, len, nullptr);
|
||||||
else
|
else
|
||||||
ReadFromBuffer (buf, len);
|
ReadFromBuffer (buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity):
|
||||||
|
LeaseSet (true), m_StoreType (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
|
{
|
||||||
|
ReadFromBufferEncrypted (buf, len, identity);
|
||||||
|
}
|
||||||
|
|
||||||
void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature)
|
void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature)
|
||||||
{
|
{
|
||||||
SetBuffer (buf, len);
|
SetBuffer (buf, len);
|
||||||
|
@ -414,7 +422,7 @@ namespace data
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len)
|
void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity)
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
// blinded key
|
// blinded key
|
||||||
|
@ -424,10 +432,12 @@ namespace data
|
||||||
if (!blindedVerifier) return;
|
if (!blindedVerifier) return;
|
||||||
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
||||||
if (offset + blindedKeyLen >= len) return;
|
if (offset + blindedKeyLen >= len) return;
|
||||||
blindedVerifier->SetPublicKey (buf + offset); offset += blindedKeyLen;
|
const uint8_t * blindedPublicKey = buf + offset;
|
||||||
|
blindedVerifier->SetPublicKey (blindedPublicKey); offset += blindedKeyLen;
|
||||||
// expiration
|
// expiration
|
||||||
if (offset + 8 >= len) return;
|
if (offset + 8 >= len) return;
|
||||||
m_PublishedTimestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds)
|
const uint8_t * publishedTimestamp = buf + offset;
|
||||||
|
m_PublishedTimestamp = bufbe32toh (publishedTimestamp); offset += 4; // published timestamp (seconds)
|
||||||
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
||||||
SetExpirationTime ((m_PublishedTimestamp + expires)*1000LL); // in milliseconds
|
SetExpirationTime ((m_PublishedTimestamp + expires)*1000LL); // in milliseconds
|
||||||
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
|
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
|
||||||
|
@ -443,11 +453,53 @@ namespace data
|
||||||
}
|
}
|
||||||
// outer ciphertext
|
// outer ciphertext
|
||||||
if (offset + 2 > len) return;
|
if (offset + 2 > len) return;
|
||||||
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2 + lenOuterCiphertext;
|
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2;
|
||||||
|
const uint8_t * outerCiphertext = buf + offset;
|
||||||
|
offset += lenOuterCiphertext;
|
||||||
// verify signature
|
// verify signature
|
||||||
bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) :
|
bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) :
|
||||||
VerifySignature (blindedVerifier, buf, len, offset);
|
VerifySignature (blindedVerifier, buf, len, offset);
|
||||||
SetIsValid (verified);
|
SetIsValid (verified);
|
||||||
|
// handle ciphertext
|
||||||
|
if (verified && identity && lenOuterCiphertext >= 32)
|
||||||
|
{
|
||||||
|
size_t l = identity->GetFullLen();
|
||||||
|
std::vector<uint8_t> destination (l);
|
||||||
|
l = identity->ToBuffer (destination.data(), l);
|
||||||
|
uint8_t credential[32], subcredential[36];
|
||||||
|
// credential = H("credential", Destination)
|
||||||
|
H ("credential", { {destination.data(), l} }, credential);
|
||||||
|
// subcredential = H("subcredential", credential || blindedPublicKey)
|
||||||
|
H ("subcredential", { {credential, 32}, {blindedPublicKey, blindedKeyLen} }, subcredential);
|
||||||
|
// outerInput = subcredential || publishedTimestamp
|
||||||
|
memcpy (subcredential + 32, publishedTimestamp, 4);
|
||||||
|
// outerSalt = outerCiphertext[32:end]
|
||||||
|
// keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44)
|
||||||
|
uint8_t outerKey[44];
|
||||||
|
HKDF (outerCiphertext + lenOuterCiphertext - 32, {subcredential, 36}, "ELS2_L1K", outerKey, 44);
|
||||||
|
// decrypt using chacha20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSet2::H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash)
|
||||||
|
{
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, p.c_str (), p.length ());
|
||||||
|
for (const auto& it: bufs)
|
||||||
|
SHA256_Update (&ctx, it.first, it.second);
|
||||||
|
SHA256_Final (hash, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSet2::HKDF (const uint8_t * salt, const std::pair<const uint8_t *, size_t>& ikm, const char * info, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
uint8_t prk[32], t[41]; unsigned int len;
|
||||||
|
HMAC(EVP_sha256(), salt, 32, ikm.first, ikm.second, prk, &len);
|
||||||
|
memcpy (t, info, 8); t[8] = 0x01;
|
||||||
|
HMAC(EVP_sha256(), prk, 32, t, 9, out, &len);
|
||||||
|
memcpy (t, out, 32); memcpy (t + 32, info, 8); t[40] = 0x02;
|
||||||
|
HMAC(EVP_sha256(), prk, 32, t, 41, t, &len);
|
||||||
|
memcpy (out + 32, t, outLen % 32); // outLen doesn't exceed 64
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
|
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
|
||||||
|
|
|
@ -133,6 +133,7 @@ namespace data
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true);
|
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true);
|
||||||
|
LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity); // store type 5, called from local netdb only
|
||||||
uint8_t GetStoreType () const { return m_StoreType; };
|
uint8_t GetStoreType () const { return m_StoreType; };
|
||||||
uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; };
|
uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; };
|
||||||
std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return m_TransientVerifier; };
|
std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return m_TransientVerifier; };
|
||||||
|
@ -144,7 +145,7 @@ namespace data
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity = true, bool verifySignature = true);
|
void ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity = true, bool verifySignature = true);
|
||||||
void ReadFromBufferEncrypted (const uint8_t * buf, size_t len);
|
void ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity);
|
||||||
size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
||||||
size_t ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
size_t ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
|
@ -153,10 +154,14 @@ namespace data
|
||||||
|
|
||||||
uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const;
|
uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const;
|
||||||
|
|
||||||
|
// for encrypted LS
|
||||||
|
void H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash);
|
||||||
|
void HKDF (const uint8_t * salt, const std::pair<const uint8_t *, size_t>& ikm, const char * info, uint8_t * out, size_t outLen); // salt - 32, info - 8
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_StoreType;
|
uint8_t m_StoreType;
|
||||||
uint32_t m_PublishedTimestamp;
|
uint32_t m_PublishedTimestamp = 0;
|
||||||
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
|
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue