Browse Source

encrypt message for ECIES router

pull/1595/head
orignal 4 years ago
parent
commit
abdf92c084
  1. 38
      libi2pd/Crypto.cpp
  2. 36
      libi2pd/ECIESX25519AEADRatchetSession.cpp
  3. 8
      libi2pd/ECIESX25519AEADRatchetSession.h
  4. 2
      libi2pd/Garlic.cpp

38
libi2pd/Crypto.cpp

@ -1333,26 +1333,31 @@ namespace crypto @@ -1333,26 +1333,31 @@ namespace crypto
// new ck is m_CK[0:31], key is m_CK[32:63]
}
static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck,
const uint8_t * hh, const uint8_t * pub)
{
// pub is Bob's public static key, hh = SHA256(h)
memcpy (state.m_CK, ck, 32);
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
}
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
{
// pub is Bob's public static key
static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
static const uint8_t hh[32] =
{
0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
}; // hh = SHA256(protocol_name || 0)
memcpy (state.m_CK, protocolName, 32); // ck = protocol_name || 0
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0
}
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
{
// pub is Bob's public static key
static const uint8_t protocolNameHash[] =
{
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
@ -1363,17 +1368,11 @@ namespace crypto @@ -1363,17 +1368,11 @@ namespace crypto
0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
}; // SHA256 (protocolNameHash)
memcpy (state.m_CK, protocolNameHash, 32);
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
InitNoiseState (state, protocolNameHash, hh, pub);
}
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
{
// pub is Bob's public static key
static const uint8_t protocolNameHash[32] =
{
0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
@ -1384,12 +1383,7 @@ namespace crypto @@ -1384,12 +1383,7 @@ namespace crypto
0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
}; // SHA256 (protocolNameHash)
memcpy (state.m_CK, protocolNameHash, 32);
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
InitNoiseState (state, protocolNameHash, hh, pub);
}
// init and terminate

36
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -490,6 +490,31 @@ namespace garlic @@ -490,6 +490,31 @@ namespace garlic
return true;
}
bool ECIESX25519AEADRatchetSession::NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Alice, router's bpk is m_RemoteStaticKey
i2p::crypto::InitNoiseNState (*this, m_RemoteStaticKey);
size_t offset = 0;
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
memcpy (out + offset, m_EphemeralKeys->GetPublicKey (), 32);
MixHash (out + offset, 32); // h = SHA256(h || aepk)
offset += 32;
uint8_t sharedSecret[32];
m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
MixKey (sharedSecret);
uint8_t nonce[12];
memset (nonce, 0, 12);
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload for router AEAD encryption failed");
return false;
}
m_State = eSessionStateNewSessionSent;
return true;
}
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob
@ -549,7 +574,7 @@ namespace garlic @@ -549,7 +574,7 @@ namespace garlic
return true;
}
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob and sent NSR already
@ -781,6 +806,11 @@ namespace garlic @@ -781,6 +806,11 @@ namespace garlic
return nullptr;
len += 96;
break;
case eSessionStateForRouter:
if (!NewOutgoingMessageForRouter (payload.data (), payload.size (), buf, m->maxLen))
return nullptr;
len += 48;
break;
default:
return nullptr;
}
@ -791,9 +821,9 @@ namespace garlic @@ -791,9 +821,9 @@ namespace garlic
return m;
}
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg)
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter)
{
m_State = eSessionStateOneTime;
m_State = isForRouter ? eSessionStateForRouter : eSessionStateOneTime;
return WrapSingleMessage (msg);
}

8
libi2pd/ECIESX25519AEADRatchetSession.h

@ -140,7 +140,8 @@ namespace garlic @@ -140,7 +140,8 @@ namespace garlic
eSessionStateNewSessionSent,
eSessionStateNewSessionReplySent,
eSessionStateEstablished,
eSessionStateOneTime
eSessionStateOneTime,
eSessionStateForRouter
};
struct DHRatchet
@ -158,7 +159,7 @@ namespace garlic @@ -158,7 +159,7 @@ namespace garlic
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg);
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter = false);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
@ -192,7 +193,8 @@ namespace garlic @@ -192,7 +193,8 @@ namespace garlic
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);

2
libi2pd/Garlic.cpp

@ -716,7 +716,7 @@ namespace garlic @@ -716,7 +716,7 @@ namespace garlic
{
auto session = std::make_shared<ECIESX25519AEADRatchetSession>(this, false);
session->SetRemoteStaticKey (router->GetIdentity ()->GetEncryptionPublicKey ());
return session->WrapOneTimeMessage (msg);
return session->WrapOneTimeMessage (msg, true);
}
else
{

Loading…
Cancel
Save