mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-10 01:01:02 +00:00
derivation of subcredentials for LeaseSet2
This commit is contained in:
parent
9aaba49a9f
commit
ea3070d02b
@ -276,6 +276,13 @@ namespace data
|
|||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t * IdentityEx::GetSigningPublicKeyBuffer () const
|
||||||
|
{
|
||||||
|
auto keyLen = GetSigningPublicKeyLen ();
|
||||||
|
if (keyLen > 128) return nullptr; // P521
|
||||||
|
return m_StandardIdentity.signingKey + 128 - keyLen;
|
||||||
|
}
|
||||||
|
|
||||||
size_t IdentityEx::GetSigningPrivateKeyLen () const
|
size_t IdentityEx::GetSigningPrivateKeyLen () const
|
||||||
{
|
{
|
||||||
if (!m_Verifier) CreateVerifier ();
|
if (!m_Verifier) CreateVerifier ();
|
||||||
|
@ -100,6 +100,7 @@ namespace data
|
|||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (const uint8_t * key) const;
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (const uint8_t * key) const;
|
||||||
size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; };
|
size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; };
|
||||||
size_t GetSigningPublicKeyLen () const;
|
size_t GetSigningPublicKeyLen () const;
|
||||||
|
const uint8_t * GetSigningPublicKeyBuffer () const; // returns NULL for P521
|
||||||
size_t GetSigningPrivateKeyLen () const;
|
size_t GetSigningPrivateKeyLen () const;
|
||||||
size_t GetSignatureLen () const;
|
size_t GetSignatureLen () const;
|
||||||
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
|
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
|
||||||
|
@ -427,7 +427,8 @@ namespace data
|
|||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
// blinded key
|
// blinded key
|
||||||
if (len < 2) return;
|
if (len < 2) return;
|
||||||
uint16_t blindedKeyType = bufbe16toh (buf + offset); offset += 2;
|
const uint8_t * stA1 = buf + offset; // stA1 = blinded signature type, 2 bytes big endian
|
||||||
|
uint16_t blindedKeyType = bufbe16toh (stA1); offset += 2;
|
||||||
std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType));
|
std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType));
|
||||||
if (!blindedVerifier) return;
|
if (!blindedVerifier) return;
|
||||||
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
||||||
@ -464,21 +465,22 @@ namespace data
|
|||||||
if (verified && identity && lenOuterCiphertext >= 32)
|
if (verified && identity && lenOuterCiphertext >= 32)
|
||||||
{
|
{
|
||||||
SetIsValid (false); // we must verify it again in Layer 2
|
SetIsValid (false); // we must verify it again in Layer 2
|
||||||
size_t l = identity->GetFullLen();
|
// credentials
|
||||||
std::vector<uint8_t> destination (l);
|
|
||||||
l = identity->ToBuffer (destination.data(), l);
|
|
||||||
// outer key
|
|
||||||
uint8_t credential[32], subcredential[36];
|
uint8_t credential[32], subcredential[36];
|
||||||
// credential = H("credential", Destination)
|
// A = destination's signing public key
|
||||||
H ("credential", { {destination.data(), l} }, credential);
|
// stA = signature type of A, 2 bytes big endian
|
||||||
|
uint16_t stA = htobe16 (identity->GetSigningKeyType ());
|
||||||
|
// credential = H("credential", A || stA || stA1)
|
||||||
|
H ("credential", { {identity->GetSigningPublicKeyBuffer (), identity->GetSigningPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {stA1, 2} }, credential);
|
||||||
// subcredential = H("subcredential", credential || blindedPublicKey)
|
// subcredential = H("subcredential", credential || blindedPublicKey)
|
||||||
H ("subcredential", { {credential, 32}, {blindedPublicKey, blindedKeyLen} }, subcredential);
|
H ("subcredential", { {credential, 32}, {blindedPublicKey, blindedKeyLen} }, subcredential);
|
||||||
|
// outer key
|
||||||
// outerInput = subcredential || publishedTimestamp
|
// outerInput = subcredential || publishedTimestamp
|
||||||
memcpy (subcredential + 32, publishedTimestamp, 4);
|
memcpy (subcredential + 32, publishedTimestamp, 4);
|
||||||
// outerSalt = outerCiphertext[0:32]
|
// outerSalt = outerCiphertext[0:32]
|
||||||
// keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44)
|
// keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44)
|
||||||
uint8_t keys[44];
|
uint8_t keys[64]; // 44 bytes actual data
|
||||||
HKDF (outerCiphertext, {subcredential, 36}, "ELS2_L1K", keys, 44);
|
HKDF (outerCiphertext, {subcredential, 36}, "ELS2_L1K", keys);
|
||||||
// decrypt Layer 1
|
// decrypt Layer 1
|
||||||
// outerKey = keys[0:31]
|
// outerKey = keys[0:31]
|
||||||
// outerIV = keys[32:43]
|
// outerIV = keys[32:43]
|
||||||
@ -489,7 +491,7 @@ namespace data
|
|||||||
// innerSalt = innerCiphertext[0:32]
|
// innerSalt = innerCiphertext[0:32]
|
||||||
// keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44)
|
// keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44)
|
||||||
// skip 1 byte flags
|
// skip 1 byte flags
|
||||||
HKDF (outerPlainText.data () + 1, {subcredential, 36}, "ELS2_L2K", keys, 44); // no authCookie
|
HKDF (outerPlainText.data () + 1, {subcredential, 36}, "ELS2_L2K", keys); // no authCookie
|
||||||
// decrypt Layer 2
|
// decrypt Layer 2
|
||||||
// innerKey = keys[0:31]
|
// innerKey = keys[0:31]
|
||||||
// innerIV = keys[32:43]
|
// innerIV = keys[32:43]
|
||||||
@ -519,15 +521,15 @@ namespace data
|
|||||||
SHA256_Final (hash, &ctx);
|
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)
|
void LeaseSet2::HKDF (const uint8_t * salt, const std::pair<const uint8_t *, size_t>& ikm, const std::string& info, uint8_t * out)
|
||||||
{
|
{
|
||||||
uint8_t prk[32], t[41]; unsigned int len;
|
uint8_t prk[32]; unsigned int len;
|
||||||
HMAC(EVP_sha256(), salt, 32, ikm.first, ikm.second, prk, &len);
|
HMAC(EVP_sha256(), salt, 32, ikm.first, ikm.second, prk, &len);
|
||||||
memcpy (t, info, 8); t[8] = 0x01;
|
auto l = info.length ();
|
||||||
HMAC(EVP_sha256(), prk, 32, t, 9, out, &len);
|
memcpy (out, info.c_str (), l); out[l] = 0x01;
|
||||||
memcpy (t, out, 32); memcpy (t + 32, info, 8); t[40] = 0x02;
|
HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len);
|
||||||
HMAC(EVP_sha256(), prk, 32, t, 41, t, &len);
|
memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02;
|
||||||
memcpy (out + 32, t, outLen % 32); // outLen doesn't exceed 64
|
HMAC(EVP_sha256(), prk, 32, out, 41, out + 32, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -156,7 +156,7 @@ namespace data
|
|||||||
|
|
||||||
// for encrypted LS
|
// for encrypted LS
|
||||||
void H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash);
|
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
|
void HKDF (const uint8_t * salt, const std::pair<const uint8_t *, size_t>& ikm, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user