std::size_t genKeyIv(char* _chunk) { char* chunk = _chunk; CryptoPP::AutoSeededRandomPool rnd; { CryptoPP::SecByteBlock key(0x00, CryptoPP::AES::DEFAULT_KEYLENGTH); rnd.GenerateBlock(key, key.size()); byte iv[CryptoPP::AES::BLOCKSIZE]; rnd.GenerateBlock(iv, sizeof(iv)); setEncKeyWithIv(key.data(), key.SizeInBytes(), iv, sizeof(iv)); std::memcpy(chunk, key.data(), key.SizeInBytes()); chunk += key.SizeInBytes(); std::memcpy(chunk, iv, sizeof(iv)); chunk += sizeof(iv); } { CryptoPP::SecByteBlock key(0x00, CryptoPP::AES::DEFAULT_KEYLENGTH); rnd.GenerateBlock(key, key.size()); byte iv[CryptoPP::AES::BLOCKSIZE]; rnd.GenerateBlock(iv, sizeof(iv)); setDecKeyWithIv(key.data(), key.SizeInBytes(), iv, sizeof(iv)); std::memcpy(chunk, key.data(), key.SizeInBytes()); chunk += key.SizeInBytes(); std::memcpy(chunk, iv, sizeof(iv)); chunk += sizeof(iv); } return chunk - _chunk; }
uint32_t generateWord32() { static CryptoPP::AutoSeededRandomPool rng; return rng.GenerateWord32(); }
void VhsmTest::testMac() { VHSM vhsm; ClientId cid; cid.pid = 0; cid.veid = 0; std::string user = "******"; std::string password = "******"; unsigned int mdsize; char msg[BUF_SIZE]; std::vector<char> md; CryptoPP::AutoSeededRandomPool rnd; rnd.GenerateBlock((byte*)msg, BUF_SIZE); byte realmd[CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE]; CryptoPP::HMAC<CryptoPP::SHA1>((byte*)"", 0).CalculateDigest(realmd, (byte*)msg, BUF_SIZE); VhsmSession s = vhsm.openSession(cid); CPPUNIT_ASSERT_MESSAGE("login user failed", vhsm.loginUser(user, password, s.sid())); CPPUNIT_ASSERT_MESSAGE("macInit failed", vhsm.macInit(HMAC, SHA1, s.sid(), "") == ERR_NO_ERROR); CPPUNIT_ASSERT_MESSAGE("unsupported method accepted", vhsm.macInit((VhsmMacMechanismId)0, (VhsmDigestMechanismId)0, s.sid(), "") == ERR_BAD_MAC_METHOD); CPPUNIT_ASSERT_MESSAGE("macUpdate failed", vhsm.macUpdate(s.sid(), std::string(msg, BUF_SIZE)) == ERR_NO_ERROR); CPPUNIT_ASSERT_MESSAGE("invalid session id accepted", vhsm.macUpdate(s.sid() + 1, std::string(msg, BUF_SIZE)) == ERR_MAC_NOT_INITIALIZED); CPPUNIT_ASSERT_MESSAGE("macGetSize failed", vhsm.macGetSize(s.sid(), &mdsize) == ERR_NO_ERROR); CPPUNIT_ASSERT_MESSAGE("wrong size returned", mdsize == CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE); CPPUNIT_ASSERT_MESSAGE("invalid session id accepted", vhsm.macGetSize(s.sid() + 1, &mdsize) == ERR_MAC_NOT_INITIALIZED); CPPUNIT_ASSERT_MESSAGE("macFinal failed", vhsm.macFinal(s.sid(), md) == ERR_NO_ERROR); CPPUNIT_ASSERT_MESSAGE("double digest finalization", vhsm.macFinal(s.sid(), md) == ERR_MAC_NOT_INITIALIZED); CPPUNIT_ASSERT_MESSAGE("wrong digest", memcmp(realmd, md.data(), CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE) == 0); CPPUNIT_ASSERT_MESSAGE("close session failed", vhsm.closeSession(cid, s)); }
SecureBinaryData SecureBinaryData::GenerateRandom(uint32_t numBytes) { static CryptoPP::AutoSeededRandomPool prng; SecureBinaryData randData(numBytes); prng.GenerateBlock(randData.getPtr(), numBytes); return randData; }
int Reseeder::ReseedNowSU3 () { CryptoPP::AutoSeededRandomPool rnd; auto ind = rnd.GenerateWord32 (0, httpReseedHostList.size() - 1); std::string reseedHost = httpReseedHostList[ind]; return ReseedFromSU3 (reseedHost); }
void generateRandomKey(std::string name, byte* key, long unsigned int length) { CryptoPP::AutoSeededRandomPool prng; //byte key[CryptoPP::AES::DEFAULT_KEYLENGTH]; prng.GenerateBlock(key, length); std::string encoded; CryptoPP::StringSource(key, length, true, new CryptoPP::HexEncoder( new CryptoPP::StringSink(encoded) ) // HexEncoder ); // StringSource std::ofstream outfile; std::string keyFile = "keys/" + name + ".key"; std::ofstream file_out(keyFile.c_str()); if(file_out.is_open()) { file_out << encoded; } //end if valid outfstream file_out.close(); }
void AddressBook::HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { if (!m_SharedLocalDestination) return; // TODO: error handling if (m_IsLoaded && !m_IsDownloading && m_SharedLocalDestination->IsReady ()) { // pick random subscription CryptoPP::AutoSeededRandomPool rnd; auto ind = rnd.GenerateWord32 (0, m_Subscriptions.size() - 1); m_IsDownloading = true; m_Subscriptions[ind]->CheckSubscription (); } else { if (!m_IsLoaded) LoadHosts (); // try it again later m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(INITIAL_SUBSCRIPTION_RETRY_TIMEOUT)); m_SubscriptionsUpdateTimer->async_wait (std::bind (&AddressBook::HandleSubscriptionsUpdateTimer, this, std::placeholders::_1)); } } }
void securityInfo::setPassword(const std::string &pw){ password=pw; CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA1> pbkdf; CryptoPP::AutoSeededRandomPool rng; rng.GenerateBlock(pwsalt,pwsalt.size()); icpw=pbkdf.DeriveKey( key, key.size(), 0x00, (byte *) password.data(), password.size(), pwsalt, pwsalt.size(), 0,0.5); iciv=pbkdf.DeriveKey(iv, iv.size(), 0x00,(byte *) password.data(), password.size(), pwsalt, pwsalt.size(), 0,0.5); }
// -------------------------------------------------------------------------- document::document () : node(std::shared_ptr<document>(this, [](document*){})), m_implementation(m_document) // -------------------------------------------------------------------------- { m_html = false; m_mode = no_quirks_mode; m_content_type = "application/xml"; m_encoding = "utf-8"; m_url = "about:blank"; if (global_object) { m_origin = global_object->m_document->m_origin; m_script_origin = global_object->m_document->m_script_origin; } else { // Default is a globally unique identifier. // We'll just generate 32 random bytes as the ID. CryptoPP::AutoSeededRandomPool rng; CryptoPP::HexEncoder enc; byte bin[32]; char hex[64]; rng.GenerateBlock(bin, 32); enc.PutMessageEnd(bin, 32); enc.Get(reinterpret_cast<byte*>(hex), 64); m_origin = hex; m_script_origin = m_origin; } }
static std::string generateChallenge() { CryptoPP::AutoSeededRandomPool prng; CryptoPP::SecByteBlock seed(16); prng.GenerateBlock(seed, seed.size()); std::string challenge; CryptoPP::ArraySource(seed, seed.size(), true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(challenge))); return challenge; }
int CEncryptedDatagramSocket::EncryptSendServer(uchar** ppbyBuf, int nBufLen, uint32 dwBaseKey) const{ ASSERT( thePrefs.IsServerCryptLayerUDPEnabled() ); ASSERT( dwBaseKey != 0 ); uint8 byPadLen = 0; // padding disabled for UDP currently uint32 nCryptedLen = nBufLen + byPadLen + CRYPT_HEADER_WITHOUTPADDING; uchar* pachCryptedBuffer = new uchar[nCryptedLen]; uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF); uchar achKeyData[7]; memcpy(achKeyData, &dwBaseKey, 4); achKeyData[4] = MAGICVALUE_UDP_CLIENTSERVER; memcpy(achKeyData + 5, &nRandomKeyPart, 2); MD5Sum md5(achKeyData, sizeof(achKeyData)); RC4_Key_Struct keySendKey; RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true); // create the semi random byte encryption header uint8 bySemiRandomNotProtocolMarker = 0; int i; for (i = 0; i < 128; i++){ bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte(); if (bySemiRandomNotProtocolMarker != OP_EDONKEYPROT) // not allowed values break; } if (i >= 128){ // either we have _real_ bad luck or the randomgenerator is a bit messed up ASSERT( false ); bySemiRandomNotProtocolMarker = 0x01; } uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_SERVER; pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker; memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2); RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey); RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey); for (int j = 0; j < byPadLen; j++){ uint8 byRand = (uint8)rand(); // they actually dont really need to be random, but it doesn't hurts either RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey); } RC4Crypt(*ppbyBuf, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, nBufLen, &keySendKey); delete[] *ppbyBuf; *ppbyBuf = pachCryptedBuffer; //Xman // Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter- /* theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen); */ theApp.pBandWidthControl->AddeMuleOutObfuscationUDP(nCryptedLen - nBufLen); //Xman end return nCryptedLen; }
uint64_t generateWord64() { static CryptoPP::AutoSeededRandomPool rng; uint64_t random; rng.GenerateBlock(reinterpret_cast<unsigned char*>(&random), 8); return random; }
bool encryptPacket(char* packet, byte* aes_key) { try { std::string plaintext(packet); //Decode the key from the file GCM< AES >::Encryption p; //iv will help us with keying out cipher //it is also randomly generated byte iv[ AES::BLOCKSIZE ]; CryptoPP::AutoSeededRandomPool prng; prng.GenerateBlock( iv, sizeof(iv) ); //Merge the iv and key p.SetKeyWithIV( aes_key, CryptoPP::AES::DEFAULT_KEYLENGTH, iv, sizeof(iv) ); //Encode the IV std::string encoded_iv; CryptoPP::StringSource(iv, sizeof(iv), true, new CryptoPP::HexEncoder( new CryptoPP::StringSink(encoded_iv) ) // HexEncoder ); //Create the ciphertext from the plaintext std::string ciphertext; CryptoPP::StringSource(plaintext, true, new CryptoPP::AuthenticatedEncryptionFilter(p, new CryptoPP::StringSink(ciphertext) ) ); //Encode the cipher to be sent std::string encodedCipher; CryptoPP::StringSource(ciphertext, true, new CryptoPP::HexEncoder( new CryptoPP::StringSink(encodedCipher) ) // HexEncoder ); //replace the packet with the econded ciphertext strcpy(packet, (encoded_iv+encodedCipher).c_str()); packet[(encoded_iv+encodedCipher).size()] = '\0'; //printf("Encrypted packet size: %d\n", (int)strlen(packet)); } catch(std::exception e) { return false; } return true; } //end encryptPacket function
std::string I2PControlSession::generateToken() const { byte random_data[I2P_CONTROL_TOKEN_SIZE] = {}; CryptoPP::AutoSeededRandomPool rng; rng.GenerateBlock(random_data, I2P_CONTROL_TOKEN_SIZE); std::string token; CryptoPP::StringSource ss( random_data, I2P_CONTROL_TOKEN_SIZE, true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(token)) ); return token; }
bool SecTpmFile::generateRandomBlock(uint8_t* res, size_t size) { try { CryptoPP::AutoSeededRandomPool rng; rng.GenerateBlock(res, size); return true; } catch (const CryptoPP::Exception& e) { return false; } }
bool Session::do_key_exchange() { aes_buffer aes_tmp; CryptoPP::AutoSeededRandomPool prng; prng.GenerateBlock(this->aes.key, sizeof(aes_key)); prng.GenerateBlock(this->aes.iv, sizeof(aes_iv)); std::memcpy(&aes_tmp, &this->aes, sizeof(aes_buffer)); CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption encryptor(aes_hard_key, sizeof(aes_key), aes_hard_iv); encryptor.ProcessData((uint8_t*)&aes_tmp, (uint8_t const*)&this->aes, sizeof(aes_buffer)); return (write(this->fd, &aes_tmp, sizeof(aes_buffer)) > 0); }
void Container::set_seed(CryptoPP::SecByteBlock seed) { seed_ = seed; CryptoPP::AutoSeededRandomPool prng; CryptoPP::SecByteBlock t(seed.size()); prng.GenerateBlock(t, t.size()); for (auto p : mtl::count_until(t.size())) { seed_[p] ^= t[p]; } prng_.IncorporateEntropy(seed_, seed_.size()); //enhance pw for (auto b : seed) { enhanced_passphrase_.push_back(b); } }
int s3fs_encrypt(int fd, byte *key) { //randomly generate iv CryptoPP::AutoSeededRandomPool prng; byte iv[CryptoPP::AES::BLOCKSIZE]; prng.GenerateBlock(iv, sizeof(iv)); string rawiv(reinterpret_cast<char*>(iv), CryptoPP::AES::BLOCKSIZE), striv; CryptoPP::StringSource s2(rawiv, true, new CryptoPP::HexEncoder( new CryptoPP::StringSink(striv) ) ); //read file into char array int flength = lseek(fd, 0, SEEK_END); unsigned char* fcontents; fcontents = (unsigned char*) calloc(flength, sizeof(char)); pread(fd, fcontents, flength, 0); string plain(reinterpret_cast<char*>(fcontents), flength); //encrypt plaintext into ciphertext string cipher; CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption e; e.SetKeyWithIV(key, CryptoPP::AES::DEFAULT_KEYLENGTH, iv); CryptoPP::StringSource ss(plain, true, new CryptoPP::StreamTransformationFilter(e, new CryptoPP::HexEncoder( new CryptoPP::StringSink(cipher) ) ) ); //write iv and encrypted data to file string output = striv+cipher; const char *buf = output.c_str(); pwrite(fd, buf, output.length(), 0); ftruncate(fd, output.length()); return 0; }
//Takes the socket and packet and sends the packet bool sendPacket(long int &csock, void* packet) { CryptoPP::AutoSeededRandomPool prng; sleepTime(prng.GenerateWord32()); //wait for random amount of time int length = 0; length = strlen((char*)packet); //printf("Packet size: %d\n", length); if(sizeof(int) != send(csock, &length, sizeof(int), 0)) { printf("[error] fail to send packet length\n"); return false; } if(length != send(csock, packet, length, 0)) { printf("[error] fail to send packet\n"); return false; } return true; }
void Pbkdf2::Work() { static const unsigned _PBKDF2_BYTE_ = 512 / 8; boost::chrono::steady_clock::time_point start = boost::chrono::steady_clock::now(); CryptoPP::SecByteBlock byte_Derived(_PBKDF2_BYTE_); CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::Whirlpool> pbkdf2; if(h_Worker == PBKDF2_GENERATE) { CryptoPP::SecByteBlock byte_Salt(_PBKDF2_BYTE_); CryptoPP::AutoSeededRandomPool RNG; RNG.GenerateBlock(byte_Salt, byte_Salt.size()); CryptoPP::ArraySource(byte_Salt, byte_Salt.size(), true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(h_Salt))); pbkdf2.DeriveKey(byte_Derived, byte_Derived.size(), 0x0, reinterpret_cast<const byte *>(h_Key.data()), h_Key.size(), reinterpret_cast<const byte *>(h_Salt.data()), h_Salt.size(), h_Iterations, 0); CryptoPP::ArraySource(byte_Derived, byte_Derived.size(), true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(h_Hash))); } else if(h_Worker == PBKDF2_VALIDATE) { pbkdf2.DeriveKey(byte_Derived, byte_Derived.size(), 0x0, reinterpret_cast<const byte *>(h_Key.data()), h_Key.size(), reinterpret_cast<const byte *>(h_Salt.data()), h_Salt.size(), h_Iterations, 0); CryptoPP::SecByteBlock byte_Validate(_PBKDF2_BYTE_); CryptoPP::StringSource(h_Hash, true, new CryptoPP::HexDecoder(new CryptoPP::ArraySink(byte_Validate, byte_Validate.size()))); // Length-constant comparison. unsigned diff = _PBKDF2_BYTE_ ^ _PBKDF2_BYTE_; for(unsigned i = 0; i < _PBKDF2_BYTE_; ++i) { diff |= byte_Derived[i] ^ byte_Validate[i]; } h_Equal = diff == 0; } boost::chrono::steady_clock::duration duration = boost::chrono::steady_clock::now() - start; h_ExecTime = static_cast<unsigned>(boost::chrono::duration_cast<boost::chrono::milliseconds>(duration).count()); }
QByteArray encrypt(QByteArray in) { byte iv[CryptoPP::AES::BLOCKSIZE]; rnd.GenerateBlock(iv, CryptoPP::AES::BLOCKSIZE); QByteArray out = QByteArray((char*)iv, CryptoPP::AES::BLOCKSIZE); int inputSize = in.size(); string cipher; CBC_Mode<AES>::Encryption aes(keyByte(), keySize(), iv); ArraySource((byte *)in.data(), inputSize, true, new StreamTransformationFilter(aes, new StringSink(cipher))); QByteArray encryptedBytes = QByteArray(cipher.c_str(), cipher.size()); out.append(encryptedBytes); return out; }
//Function generates a random alphanumeric string of length len std::string randomString(const unsigned int len) { static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; CryptoPP::AutoSeededRandomPool prng; std::string s = ""; //When adding each letter, generate a new word32, //then compute it modulo alphanum's size - 1 for(unsigned int i = 0; i < len; ++i) { s += alphanum[prng.GenerateWord32() % (sizeof(alphanum) - 1)]; } //end for generate random string /*std::string s = ""; for (int i = 0; i < len; ++i) { s += alphanum[rand() % (sizeof(alphanum) - 1)]; } */ return s; }
void KadFileDownloader::Init() { uchar achKeyData[21]; uint32 m_nRandomKeyPart = cryptRandomGen.GenerateWord32(); md4cpy(achKeyData,&KadUtil::client_hash); memcpy(achKeyData+17,&m_nRandomKeyPart,4); uchar md5sum[16]={0}; MD5 md5; md5.Update(achKeyData,sizeof(achKeyData)); md5.Final(md5sum); achKeyData[16] = MAGICVALUE_REQUESTER; m_pRC4SendKey= RC4CreateKey(md5sum,16,NULL); achKeyData[16] = MAGICVALUE_SERVER; md5.Update(achKeyData,sizeof(achKeyData)); md5.Final(md5sum); m_pRC4ReceiveKey = RC4CreateKey(md5sum,16,NULL); creditsPool.InitalizeCrypting(); }
void CEncryptedStreamSocket::SetConnectionEncryption(bool bEnabled, const uchar* pTargetClientHash, bool bServerConnection){ if (m_StreamCryptState != ECS_UNKNOWN && m_StreamCryptState != ECS_NONE){ if (!m_StreamCryptState == ECS_NONE || bEnabled) ASSERT( false ); return; } ASSERT( m_pRC4SendKey == NULL ); ASSERT( m_pRC4ReceiveKey == NULL ); if (bEnabled && pTargetClientHash != NULL && !bServerConnection){ m_StreamCryptState = ECS_PENDING; // create obfuscation keys, see on top for key format // use the crypt random generator m_nRandomKeyPart = cryptRandomGen.GenerateWord32(); uchar achKeyData[21]; md4cpy(achKeyData, pTargetClientHash); memcpy(achKeyData + 17, &m_nRandomKeyPart, 4); achKeyData[16] = MAGICVALUE_REQUESTER; MD5Sum md5(achKeyData, sizeof(achKeyData)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); achKeyData[16] = MAGICVALUE_SERVER; md5.Calculate(achKeyData, sizeof(achKeyData)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); } else if (bServerConnection && bEnabled){ m_bServerCrypt = true; m_StreamCryptState = ECS_PENDING_SERVER; } else{ ASSERT( !bEnabled ); m_StreamCryptState = ECS_NONE; } }
uint8_t CEncryptedStreamSocket::GetSemiRandomNotProtocolMarker() const{ uint8_t bySemiRandomNotProtocolMarker = 0; int i; for (i = 0; i < 128; i++){ bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte(); bool bOk = false; switch (bySemiRandomNotProtocolMarker){ // not allowed values case OP_EDONKEYPROT: case OP_PACKEDPROT: case OP_EMULEPROT: break; default: bOk = true; } if (bOk) break; } if (i >= 128){ // either we have _real_ bad luck or the randomgenerator is a bit messed up ASSERT( false ); bySemiRandomNotProtocolMarker = 0x01; } return bySemiRandomNotProtocolMarker; }
void CUTPSocketListner::Send(const byte* Buff, size_t uSize, const struct sockaddr* sa, socklen_t sa_len, uint8 Type) { TKeyMap::iterator I = m_SendKeys.find((struct sockaddr*)sa); if(I == m_SendKeys.end()) return; I->second->LastActivity = GetCurTick(); ASSERT(I->second->PassKey); if(uSize > 0xFFFF - 0x80) { ASSERT(0); return; } bool SendKey = false; int PadLen = 16; if(Type == 1) // if its a UTP packet lets be a bit smart { ASSERT(uSize >= 4); UUtpHdr UtpHdr; UtpHdr.Bits = *((uint32*)Buff); if(UtpHdr.Fields.type == 4) // ST_SYN SendKey = true; // we always send the passked on y UTP Sync packet if(UtpHdr.Fields.type == 0) // ST_DATA PadLen = 0; // we dont needto padd data frames as tahy may already on thair own have a random size } else //if(!I->second->bAck) // if we are not talking UDT lets always send the key just to be sure SendKey = true; char Buffer[0xFFFF]; byte* pBuffer = (byte*)Buffer; size_t uLength = 0; CryptoPP::AutoSeededRandomPool rng; uint32 Rand = 0; rng.GenerateBlock((byte*)&Rand, sizeof(uint32)); UHdr Hdr; Hdr.Fields.Type = Type; Hdr.Fields.Reserved = 0; Hdr.Fields.Discard = 0; // total drop ist (n+1)*256 if(uSize >= 10 * 1024) Hdr.Fields.Discard = 3; // discard only 1024 key bytes in total for large packets Hdr.Fields.HasKey = SendKey; if(PadLen) PadLen = (rand() % (PadLen + 1)) & 0x3F; // ensure 64 bytes are available for optional footer entries Hdr.Fields.PadLen = PadLen; //if(Hdr.Fields.Reserved != 0) // Hdr.Fields.PadLen += 4; memcpy(pBuffer + uLength, &Rand, sizeof(uint32)); uLength += 4; memcpy(pBuffer + uLength, &Hdr.Bits, sizeof(uint32)); uLength += 4; if(Hdr.Fields.HasKey) { memcpy(pBuffer + uLength, &m_RecvKey, sizeof(uint64)); uLength += 8; } memcpy(pBuffer + uLength, Buff, uSize); uLength += uSize; //if(Hdr.Fields.Reserved != 0) { // memcpy(pBuffer + uLength, NEO_MAGIC, 4); uLength += 4; } if(PadLen > 0) { rng.GenerateBlock(pBuffer + uLength, PadLen); uLength += PadLen; } CryptoPP::Weak1::MD5 md5; md5.Update((byte*)&Rand, sizeof(Rand)); md5.Update((byte*)&I->second->PassKey, sizeof(uint64)); byte Hash[16]; md5.Final(Hash); //#ifdef _DEBUG // LogLine(LOG_INFO | LOG_DEBUG, L"Send to %s PassKey %I64u -> %s", // CSafeAddress(sa, sa_len, sa_len == sizeof(sockaddr_in) ? CSafeAddress::eUTP_IP4 : CSafeAddress::eUTP_IP6).ToString().c_str(), // I->second->PassKey, ToHex(Hash, 16).c_str()); //#endif CryptoPP::Weak::ARC4::Encryption RC4; RC4.SetKey(Hash, 16); RC4.DiscardBytes(256); RC4.ProcessData(pBuffer + 4, pBuffer + 4, 4); if(Hdr.Fields.Discard) RC4.DiscardBytes(Hdr.Fields.Discard * 256); RC4.ProcessData(pBuffer + 8, pBuffer + 8, uLength - 8); sendto(m_Socket, Buffer, (int)uLength, 0, (struct sockaddr*)sa, sa_len); }
// Encrypt packet. Key used: // pachClientHashOrKadID != NULL -> pachClientHashOrKadID // pachClientHashOrKadID == NULL && bKad && nReceiverVerifyKey != 0 -> nReceiverVerifyKey // else -> ASSERT int CEncryptedDatagramSocket::EncryptSendClient(uchar** ppbyBuf, int nBufLen, const uchar* pachClientHashOrKadID, bool bKad, uint32 nReceiverVerifyKey, uint32 nSenderVerifyKey) const{ ASSERT( theApp.GetPublicIP() != 0 || bKad ); ASSERT( thePrefs.IsClientCryptLayerSupported() ); ASSERT( pachClientHashOrKadID != NULL || nReceiverVerifyKey != 0 ); ASSERT( (nReceiverVerifyKey == 0 && nSenderVerifyKey == 0) || bKad ); uint8 byPadLen = 0; // padding disabled for UDP currently const uint32 nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 8 : 0); uint32 nCryptedLen = nBufLen + nCryptHeaderLen; uchar* pachCryptedBuffer = new uchar[nCryptedLen]; bool bKadRecKeyUsed = false; uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF); MD5Sum md5; if (bKad){ if ((pachClientHashOrKadID == NULL || isnulmd4(pachClientHashOrKadID)) && nReceiverVerifyKey != 0) { bKadRecKeyUsed = true; uchar achKeyData[6]; PokeUInt32(achKeyData, nReceiverVerifyKey); PokeUInt16(achKeyData+4, nRandomKeyPart); md5.Calculate(achKeyData, sizeof(achKeyData)); //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) ); } else if (pachClientHashOrKadID != NULL && !isnulmd4(pachClientHashOrKadID)) { uchar achKeyData[18]; md4cpy(achKeyData, pachClientHashOrKadID); PokeUInt16(achKeyData+16, nRandomKeyPart); md5.Calculate(achKeyData, sizeof(achKeyData)); //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) ); } else { ASSERT( false ); delete[] pachCryptedBuffer; return nBufLen; } } else{ uchar achKeyData[23]; md4cpy(achKeyData, pachClientHashOrKadID); uint32 dwIP = theApp.GetPublicIP(); memcpy(achKeyData+16, &dwIP, 4); memcpy(achKeyData+21, &nRandomKeyPart, 2); achKeyData[20] = MAGICVALUE_UDP; md5.Calculate(achKeyData, sizeof(achKeyData)); } RC4_Key_Struct keySendKey; RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true); // create the semi random byte encryption header uint8 bySemiRandomNotProtocolMarker = 0; int i; for (i = 0; i < 128; i++){ bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte(); bySemiRandomNotProtocolMarker = bKad ? (bySemiRandomNotProtocolMarker & 0xFE) : (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit if (bKad) bySemiRandomNotProtocolMarker = bKadRecKeyUsed ? ((bySemiRandomNotProtocolMarker & 0xFE) | 0x02) : (bySemiRandomNotProtocolMarker & 0xFC); // set the ed2k/kad and nodeid/reckey markerbit else bySemiRandomNotProtocolMarker = (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit bool bOk = false; switch (bySemiRandomNotProtocolMarker){ // not allowed values case OP_EMULEPROT: case OP_KADEMLIAPACKEDPROT: case OP_KADEMLIAHEADER: case OP_UDPRESERVEDPROT1: case OP_UDPRESERVEDPROT2: case OP_PACKEDPROT: break; default: bOk = true; } if (bOk) break; } if (i >= 128){ // either we have _really_ bad luck or the randomgenerator is a bit messed up ASSERT( false ); bySemiRandomNotProtocolMarker = 0x01; } uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT; pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker; memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2); RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey); RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey); for (int j = 0; j < byPadLen; j++){ uint8 byRand = (uint8)rand(); // they actually dont really need to be random, but it doesn't hurts either RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey); } if (bKad){ RC4Crypt((uchar*)&nReceiverVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, 4, &keySendKey); RC4Crypt((uchar*)&nSenderVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4, 4, &keySendKey); } RC4Crypt(*ppbyBuf, pachCryptedBuffer + nCryptHeaderLen, nBufLen, &keySendKey); delete[] *ppbyBuf; *ppbyBuf = pachCryptedBuffer; //Xman // Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter- /* theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen); */ theApp.pBandWidthControl->AddeMuleOutObfuscationUDP(nCryptedLen - nBufLen); //Xman end return nCryptedLen; }
int CEncryptedStreamSocket::Negotiate(const uchar* pBuffer, uint32_t nLen){ uint32_t nRead = 0; ASSERT( m_nReceiveBytesWanted > 0 ); try{ while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0){ if (m_nReceiveBytesWanted > 512){ ASSERT( false ); return 0; } if (m_pfiReceiveBuffer == NULL){ BYTE* pReceiveBuffer = (BYTE*)malloc(512); // use a fixed size buffer if (pReceiveBuffer == NULL) AfxThrowMemoryException(); m_pfiReceiveBuffer = new CSafeMemFile(pReceiveBuffer, 512); } const uint32_t nToRead = min(nLen - nRead, m_nReceiveBytesWanted); m_pfiReceiveBuffer->Write(pBuffer + nRead, nToRead); nRead += nToRead; m_nReceiveBytesWanted -= nToRead; if (m_nReceiveBytesWanted > 0) return nRead; const uint32_t nCurrentBytesLen = (uint32_t)m_pfiReceiveBuffer->GetPosition(); if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER){ // don't have the keys yet BYTE* pCryptBuffer = m_pfiReceiveBuffer->Detach(); RC4Crypt(pCryptBuffer, pCryptBuffer, nCurrentBytesLen, m_pRC4ReceiveKey); m_pfiReceiveBuffer->Attach(pCryptBuffer, 512); } m_pfiReceiveBuffer->SeekToBegin(); switch (m_NegotiatingState){ case ONS_NONE: // would be a bug ASSERT( false ); return 0; case ONS_BASIC_CLIENTA_RANDOMPART:{ ASSERT( m_pRC4ReceiveKey == NULL ); uchar achKeyData[21]; md4cpy(achKeyData, thePrefs.GetUserHash()); achKeyData[16] = MAGICVALUE_REQUESTER; m_pfiReceiveBuffer->Read(achKeyData + 17, 4); // random key part sent from remote client MD5Sum md5(achKeyData, sizeof(achKeyData)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); achKeyData[16] = MAGICVALUE_SERVER; md5.Calculate(achKeyData, sizeof(achKeyData)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_CLIENTA_MAGICVALUE:{ uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32(); if (dwValue == MAGICVALUE_SYNC){ // yup, the one or the other way it worked, this is an encrypted stream //DEBUG_ONLY( DebugLog(_T("Received proper magic value, clientIP: %s"), DbgGetIPString()) ); // set the receiver key m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else{ DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_CLIENTA_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTA_PADDING; //if (m_nReceiveBytesWanted > 16) // AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted); if (m_nReceiveBytesWanted > 0) break; case ONS_BASIC_CLIENTA_PADDING:{ // ignore the random bytes, send the response, set status complete CSafeMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); SOCKADDR_IN sockAddr = {0}; int nSockAddrLen = sizeof(sockAddr); GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); const uint8_t byPaddingLen = theApp.serverconnect->AwaitingTestFromIP(sockAddr.sin_addr.S_un.S_addr) ? 16 : (thePrefs.GetCryptTCPPaddingLength() + 1); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % byPaddingLen); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF)); SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength()); m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) ); break; } case ONS_BASIC_CLIENTB_MAGICVALUE:{ if (m_pfiReceiveBuffer->ReadUInt32() != MAGICVALUE_SYNC){ DebugLogError(_T("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } m_NegotiatingState = ONS_BASIC_CLIENTB_METHODTAGSPADLEN; m_nReceiveBytesWanted = 2; break; } case ONS_BASIC_CLIENTB_METHODTAGSPADLEN:{ m_dbgbyEncryptionMethodSet = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionMethodSet != ENM_OBFUSCATION){ DebugLogError( _T("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"), DbgGetIPString(), m_dbgbyEncryptionMethodSet); OnError(ERR_ENCRYPTION); return (-1); } m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTB_PADDING; if (m_nReceiveBytesWanted > 0) break; } case ONS_BASIC_CLIENTB_PADDING: // ignore the random bytes, the handshake is complete m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) ); break; case ONS_BASIC_SERVER_DHANSWER:{ ASSERT( !m_cryptDHA.IsZero() ); uchar aBuffer[PRIMESIZE_BYTES + 1]; m_pfiReceiveBuffer->Read(aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHAnswer((byte*)aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime CryptoPP::Integer cryptResult = CryptoPP::a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime); m_cryptDHA = 0; DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) ); ASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES ); // create the keys cryptResult.Encode(aBuffer, PRIMESIZE_BYTES); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER; MD5Sum md5(aBuffer, sizeof(aBuffer)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER; md5.Calculate(aBuffer, sizeof(aBuffer)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); m_NegotiatingState = ONS_BASIC_SERVER_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_SERVER_MAGICVALUE:{ uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32(); if (dwValue == MAGICVALUE_SYNC){ // yup, the one or the other way it worked, this is an encrypted stream DebugLog(_T("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString()); // set the receiver key m_NegotiatingState = ONS_BASIC_SERVER_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else{ DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_SERVER_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_SERVER_PADDING; if (m_nReceiveBytesWanted > 16) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted); if (m_nReceiveBytesWanted > 0) break; case ONS_BASIC_SERVER_PADDING:{ // ignore the random bytes (they are decrypted already), send the response, set status complete CSafeMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF)); m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING; SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength(), 0, true); // don't actually send it right now, store it in our sendbuffer m_StreamCryptState = ECS_ENCRYPTING; DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString()) ); break; } default: ASSERT( false ); } m_pfiReceiveBuffer->SeekToBegin(); } if (m_pfiReceiveBuffer != NULL) free(m_pfiReceiveBuffer->Detach()); delete m_pfiReceiveBuffer; m_pfiReceiveBuffer = NULL; return nRead; } catch(CFileException* error){ // can only be caused by a bug in negationhandling, not by the datastream error->Delete(); ASSERT( false ); OnError(ERR_ENCRYPTION); if (m_pfiReceiveBuffer != NULL) free(m_pfiReceiveBuffer->Detach()); delete m_pfiReceiveBuffer; m_pfiReceiveBuffer = NULL; return (-1); } }
void CEncryptedStreamSocket::StartNegotiation(bool bOutgoing){ if (!bOutgoing){ m_NegotiatingState = ONS_BASIC_CLIENTA_RANDOMPART; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 4; } else if (m_StreamCryptState == ECS_PENDING){ CSafeMemFile fileRequest(29); const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker(); fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker); fileRequest.WriteUInt32(m_nRandomKeyPart); fileRequest.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySupportedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version fileRequest.WriteUInt8(bySupportedEncryptionMethod); fileRequest.WriteUInt8(bySupportedEncryptionMethod); // so we also prefer this one uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % (thePrefs.GetCryptTCPPaddingLength() + 1)); fileRequest.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileRequest.WriteUInt8(cryptRandomGen.GenerateByte()); m_NegotiatingState = ONS_BASIC_CLIENTB_MAGICVALUE; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 4; SendNegotiatingData(fileRequest.GetBuffer(), (uint32_t)fileRequest.GetLength(), 5); } else if (m_StreamCryptState == ECS_PENDING_SERVER){ CSafeMemFile fileRequest(113); const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker(); fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker); m_cryptDHA.Randomize(cryptRandomGen, DHAGREEMENT_A_BITS); // our random a ASSERT( m_cryptDHA.MinEncodedSize() <= DHAGREEMENT_A_BITS / 8 ); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime // calculate g^a % p CryptoPP::Integer cryptDHGexpAmodP = CryptoPP::a_exp_b_mod_c(CryptoPP::Integer(2), m_cryptDHA, cryptDHPrime); ASSERT( m_cryptDHA.MinEncodedSize() <= PRIMESIZE_BYTES ); // put the result into a buffer uchar aBuffer[PRIMESIZE_BYTES]; cryptDHGexpAmodP.Encode(aBuffer, PRIMESIZE_BYTES); fileRequest.Write(aBuffer, PRIMESIZE_BYTES); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16); // add random padding fileRequest.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileRequest.WriteUInt8(cryptRandomGen.GenerateByte()); m_NegotiatingState = ONS_BASIC_SERVER_DHANSWER; m_StreamCryptState = ECS_NEGOTIATING; m_nReceiveBytesWanted = 96; SendNegotiatingData(fileRequest.GetBuffer(), (uint32_t)fileRequest.GetLength(), (uint32_t)fileRequest.GetLength()); } else{ ASSERT( false ); m_StreamCryptState = ECS_NONE; return; } }
int CEncryptedDatagramSocket::EncryptSendClient(uchar** ppbyBuf, int nBufLen, const uchar* pachClientHashOrKadID, bool bKad, uint16 nReceiverVerifyKey, uint16 nSenderVerifyKey) const{ ASSERT( theApp.GetPublicIP() != 0 || bKad ); ASSERT( thePrefs.IsClientCryptLayerSupported() ); uint8 byPadLen = 0; // padding disabled for UDP currently const uint32 nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 4 : 0); uint32 nCryptedLen = nBufLen + nCryptHeaderLen; uchar* pachCryptedBuffer = new uchar[nCryptedLen]; uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF); MD5Sum md5; if (bKad){ uchar achKeyData[18]; md4cpy(achKeyData, pachClientHashOrKadID); memcpy(achKeyData+16, &nRandomKeyPart, 2); md5.Calculate(achKeyData, sizeof(achKeyData)); } else{ uchar achKeyData[23]; md4cpy(achKeyData, pachClientHashOrKadID); uint32 dwIP = theApp.GetPublicIP(); memcpy(achKeyData+16, &dwIP, 4); memcpy(achKeyData+21, &nRandomKeyPart, 2); achKeyData[20] = MAGICVALUE_UDP; md5.Calculate(achKeyData, sizeof(achKeyData)); } RC4_Key_Struct keySendKey; RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true); // create the semi random byte encryption header uint8 bySemiRandomNotProtocolMarker = 0; int i; for (i = 0; i < 128; i++){ bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte(); bySemiRandomNotProtocolMarker = bKad ? (bySemiRandomNotProtocolMarker & 0xFE) : (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit bool bOk = false; switch (bySemiRandomNotProtocolMarker){ // not allowed values case OP_EMULEPROT: case OP_KADEMLIAPACKEDPROT: case OP_KADEMLIAHEADER: case OP_UDPRESERVEDPROT1: case OP_UDPRESERVEDPROT2: case OP_PACKEDPROT: break; default: bOk = true; } if (bOk) break; } if (i >= 128){ // either we have _real_ bad luck or the randomgenerator is a bit messed up ASSERT( false ); bySemiRandomNotProtocolMarker = 0x01; } uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT; pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker; memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2); RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey); RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey); for (int j = 0; j < byPadLen; j++){ uint8 byRand = (uint8)rand(); // they actually dont really need to be random, but it doesn't hurts either RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey); } if (bKad){ RC4Crypt((uchar*)&nReceiverVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, 2, &keySendKey); RC4Crypt((uchar*)&nSenderVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 2, 2, &keySendKey); } RC4Crypt(*ppbyBuf, pachCryptedBuffer + nCryptHeaderLen, nBufLen, &keySendKey); delete[] *ppbyBuf; *ppbyBuf = pachCryptedBuffer; theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen); return nCryptedLen; }