From e0e5e8ad36b229b992fce1d7ab23572f97a2c7df Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 23 Nov 2013 16:35:15 -0500 Subject: [PATCH] Initial commit of garlic --- ElGamal.h | 18 +++++++++---- Garlic.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Garlic.h | 30 +++++++++++++++++++++ 3 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 Garlic.cpp create mode 100644 Garlic.h diff --git a/ElGamal.h b/ElGamal.h index f9b5ff65..387e02bb 100644 --- a/ElGamal.h +++ b/ElGamal.h @@ -12,23 +12,31 @@ namespace i2p { namespace crypto { - inline void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, int len, uint8_t * encrypted) + inline void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, int len, + uint8_t * encrypted, bool zeroPadding = false) // 514 with padding and 512 without { CryptoPP::AutoSeededRandomPool rnd; CryptoPP::Integer y(key, 256), k(rnd, CryptoPP::Integer::One(), elgp-1); - a_exp_b_mod_c (elgg, k, elgp).Encode (encrypted, 256); + if (zeroPadding) + { + encrypted[0] = 0; + encrypted[257] = 0; + } + a_exp_b_mod_c (elgg, k, elgp).Encode (zeroPadding ? encrypted + 1 : encrypted, 256); uint8_t m[255]; m[0] = 0xFF; memcpy (m+33, data, len); CryptoPP::SHA256().CalculateDigest(m+1, m+33, 222); a_times_b_mod_c (a_exp_b_mod_c (y, k, elgp), - CryptoPP::Integer (m, 255), elgp).Encode (encrypted + 256, 256); + CryptoPP::Integer (m, 255), elgp).Encode (zeroPadding ? encrypted + 258 : encrypted + 256, 256); } - inline bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data) + inline bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, + uint8_t * data, bool zeroPadding = false) { - CryptoPP::Integer x(key, 256), a(encrypted, 256), b(encrypted + 256, 256); + CryptoPP::Integer x(key, 256), a(zeroPadding? encrypted +1 : encrypted, 256), + b(zeroPadding? encrypted + 258 :encrypted + 256, 256); uint8_t m[255], hash[32]; a_times_b_mod_c (b, a_exp_b_mod_c (a, elgp - x - 1, elgp), elgp).Encode (m, 255); CryptoPP::SHA256().CalculateDigest(hash, m+33, 222); diff --git a/Garlic.cpp b/Garlic.cpp new file mode 100644 index 00000000..d829fd71 --- /dev/null +++ b/Garlic.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include "RouterContext.h" +#include "Timestamp.h" +#include "ElGamal.h" +#include "Garlic.h" + +namespace i2p +{ + I2NPMessage * WrapI2NPMessage (const uint8_t * encryptionKey, I2NPMessage * msg) + { + CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); + // create ElGamal block + ElGamalBlock elGamal; + rnd.GenerateBlock (elGamal.sessionKey, 32); // session key + rnd.GenerateBlock (elGamal.preIV, 32); // Pre-IV + uint8_t iv[32]; // IV is first 16 bytes + CryptoPP::SHA256().CalculateDigest(iv, elGamal.preIV, 32); + + CryptoPP::CBC_Mode::Encryption encryption; + encryption.SetKeyWithIV (elGamal.sessionKey, 32, iv); + + I2NPMessage * m = NewI2NPMessage (); + uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length + i2p::crypto::ElGamalEncrypt (encryptionKey, (uint8_t *)&elGamal, sizeof(elGamal), buf, true); + buf += 514; + size_t blockSize = 0; + *(uint16_t *)buf = 0; // tag count + blockSize += 2; + uint32_t * payloadSize = (uint32_t *)(buf + blockSize); + blockSize += 4; + uint8_t * payloadHash = buf + blockSize; + blockSize += 32; + buf[blockSize] = 0; // flag + blockSize++; + size_t len = CreateGarlicPayload (buf + blockSize, msg); + *payloadSize = htobe32 (len); + CryptoPP::SHA256().CalculateDigest(payloadHash, buf + blockSize, len); + blockSize += len; + size_t rem = blockSize % 16; + if (rem) + blockSize += (16-rem); //padding + encryption.ProcessData(buf, buf, blockSize); + + *(uint32_t *)(m->GetPayload ()) = htobe32 (blockSize + 514); + m->len += blockSize + 514 + 4; + FillI2NPMessageHeader (m, eI2NPGarlic); + DeleteI2NPMessage (msg); + return m; + } + + size_t CreateGarlicPayload (uint8_t * payload, I2NPMessage * msg) + { + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); + size_t size = 0; + payload[size] = 1; // 1 clove + size++; + payload[size] = 0;// delivery instructions flag + size++; + memcpy (payload + size, msg->GetBuffer (), msg->GetLength ()); + size += msg->GetLength (); + *(uint32_t *)(payload + size) = htobe32 (1011); // CloveID + size += 4; + *(uint64_t *)(payload + size) = htobe64 (ts); // Expiration of clove + size += 8; + memset (payload + size, 0, 3); // certificate of clove + size += 3; + memset (payload + size, 0, 3); // certificate of message + size += 3; + *(uint32_t *)(payload + size) = htobe32 (2022); // MessageID + size += 4; + *(uint64_t *)(payload + size) = htobe64 (ts); // Expiration of message + size += 8; + return size; + } +} \ No newline at end of file diff --git a/Garlic.h b/Garlic.h new file mode 100644 index 00000000..0518f36c --- /dev/null +++ b/Garlic.h @@ -0,0 +1,30 @@ +#ifndef GARLIC_H__ +#define GARLIC_H__ + +#include +#include "I2NPProtocol.h" + +namespace i2p +{ + enum GarlicDeliveryType + { + eGarlicDeliveryTypeLocal = 0, + eGarlicDeliveryTypeDestination = 1, + eGarlicDeliveryTypeRouter = 2, + eGarlicDeliveryTypeTunnel = 3 + }; + +#pragma pack(1) + struct ElGamalBlock + { + uint8_t sessionKey[32]; + uint8_t preIV[32]; + uint8_t padding[158]; + }; +#pragma pack() + + I2NPMessage * WrapI2NPMessage (const uint8_t * encryptionKey, I2NPMessage * msg); + size_t CreateGarlicPayload (uint8_t * payload, I2NPMessage * msg); +} + +#endif