void CKadHandler::HandleCryptoRequest(const CVariant& Request, CKadNode* pNode, CComChannel* pChannel) { SKadData* pData = pChannel->GetData<SKadData>(); if(GetParent<CKademlia>()->Cfg()->GetBool("DebugTL")) LogLine(LOG_DEBUG, L"Recived 'CryptoRequest' to %s", pNode->GetID().ToHex().c_str()); CVariant Response(CVariant::EMap); CScoped<CSymmetricKey> pCryptoKey; try { CScoped<CAbstractKey> pSessionKey; if(Request.Has("EK")) { UINT eExAlgorithm = 0; string Param; if(Request.Has("KA")) eExAlgorithm = ParseKA(Request["KA"], Param); UINT eAlgorithm = PrepKA(eExAlgorithm, Param); CScoped<CKeyExchange> pKeyExchange = NewKeyExchange(eAlgorithm, Param); CScoped<CAbstractKey> pKey = pKeyExchange->InitialsieKeyExchange(); Response["EK"] = CVariant(pKey->GetKey(), pKey->GetSize()); CScoped<CAbstractKey> pRemKey = new CAbstractKey(Request["EK"].GetData(), Request["EK"].GetSize()); pSessionKey = pKeyExchange->FinaliseKeyExchange(pRemKey); if(!pSessionKey) throw "ExchangeFailed"; bool bAuthenticated = Request.IsSigned(); if(bAuthenticated) { CPublicKey* pPubKey; if(Request.Has("PK")) pPubKey = pNode->SetIDKey(Request); else pPubKey = pNode->GetID().GetKey(); if(!pPubKey) throw "MissingKey"; if(!Request.Verify(pPubKey)) throw "InvalidSign"; } pData->Authenticated = bAuthenticated; pNode->SetTrustedKey(new CTrustedKey(pSessionKey->GetKey(), pSessionKey->GetSize(), bAuthenticated, eAlgorithm & CAbstractKey::eHashFunkt)); } else if(Request.Has("FP")) { CTrustedKey* pTrustedKey = pNode->GetTrustedKey(); if(!pTrustedKey || pTrustedKey->GetFingerPrint() != Request["FP"].To<uint64>()) throw "UnknownKey"; pData->Authenticated = pTrustedKey->IsAuthenticated(); pSessionKey = new CAbstractKey(pTrustedKey->GetKey(), pTrustedKey->GetSize()); } else throw "UnknownMethod"; if(Request.Has("IV")) { CAbstractKey OutIV(KEY_128BIT, true); Response["IV"] = CVariant(OutIV.GetKey(), OutIV.GetSize()); UINT eSymAlgorithm = 0; if(Request.Has("SC")) eSymAlgorithm = ParseSC(Request["SC"]); UINT eAlgorithm = PrepSC(eSymAlgorithm); CAbstractKey InIV(Request["IV"].GetData(), Request["IV"].GetSize()); pCryptoKey = NewSymmetricKey(eAlgorithm, pSessionKey, &InIV, &OutIV); } if(Request.IsSigned() && pData->Authenticated) { const CMyKadID& MyID = GetParent<CKademlia>()->Root()->GetID(); Response["PK"] = CVariant(MyID.GetKey()->GetKey(), MyID.GetKey()->GetSize()); if((MyID.GetKey()->GetAlgorithm() & CAbstractKey::eHashFunkt) != 0) Response["HK"] = CAbstractKey::Algorithm2Str((MyID.GetKey()->GetAlgorithm() & CAbstractKey::eHashFunkt)); Response.Sign(MyID.GetPrivateKey()); } } catch(const char* Error) { delete pCryptoKey.Detache(); Response["ERR"] = Error; } if(GetParent<CKademlia>()->Cfg()->GetBool("DebugTL")) LogLine(LOG_DEBUG, L"Sending 'CryptoResponse' to %s", pNode->GetID().ToHex().c_str()); pChannel->SendPacket(KAD_CRYPTO_RESPONSE, Response); if(pCryptoKey) { pChannel->SetQueueLock(true); pChannel->Encrypt(pCryptoKey.Detache()); pChannel->SetQueueLock(false); } }