#ifndef EL_GAMAL_H__ #define EL_GAMAL_H__ #include #include #include #include #include "CryptoConst.h" #include "Log.h" namespace i2p { namespace crypto { 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); 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 (zeroPadding ? encrypted + 258 : encrypted + 256, 256); } inline bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, bool zeroPadding = false) { 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); for (int i = 0; i < 32; i++) if (hash[i] != m[i+1]) { LogPrint ("ElGamal decrypt hash doesn't match"); return false; } memcpy (data, m + 33, 222); return true; } } } #endif