//--------------------------------------------------------------------- ElementPtr PeerContactProfile::getPrivateProfile() const { AutoRecursiveLock lock(mLock); if (!mDocument) return ElementPtr(); if (!hasContactProfileSecret()) return ElementPtr(); try { ElementPtr contactProfileElement = getContactProfileElement(); if (!contactProfileElement) return ElementPtr(); ElementPtr privateElement = contactProfileElement->findFirstChildElementChecked("private"); ElementPtr profileElement = privateElement->findFirstChildElementChecked("encryptedProfile"); ElementPtr saltElement = privateElement->findFirstChildElementChecked("salt"); String saltAsBase64 = saltElement->getText(true); SecureByteBlock output; decryptAndNulTerminateFromBase64( "profile", mContactProfileSecret, saltAsBase64, profileElement->getText(true), output ); String parseData = (CSTR)((const BYTE *)output); DocumentPtr temp = Document::create(); temp->parse(parseData); ElementPtr result = temp->findFirstChildElementChecked("profile"); result->orphan(); return result; } catch (zsLib::XML::Exceptions::CheckFailed &) { } return ElementPtr(); }
//--------------------------------------------------------------------- IPeerFilePublicPtr PeerContactProfile::getPeerFilePublic() const { AutoRecursiveLock lock(mLock); PeerFilesPtr outer = mPeerFiles.lock(); if (outer) { IPeerFilePublicPtr publicPeer = outer->getPublic(); if (publicPeer) return publicPeer; } if (!mDocument) return IPeerFilePublicPtr(); if (!hasContactProfileSecret()) return IPeerFilePublicPtr(); try { ElementPtr contactProfileElement = getContactProfileElement(); if (!contactProfileElement) return IPeerFilePublicPtr(); ElementPtr privateElement = contactProfileElement->findFirstChildElementChecked("private"); ElementPtr encryptedPeerElement = privateElement->findFirstChildElementChecked("encryptedPeer"); ElementPtr saltElement = privateElement->findFirstChildElementChecked("salt"); String saltAsBase64 = saltElement->getText(true); SecureByteBlock output; decryptAndNulTerminateFromBase64( "peer", mContactProfileSecret, saltAsBase64, encryptedPeerElement->getText(true), output ); String parseData = (CSTR)((const BYTE *)output); DocumentPtr temp = Document::create(); temp->parse(parseData); ElementPtr result = temp->findFirstChildElementChecked("peer"); result->orphan(); PeerFilePublicPtr publicPeer = PeerFilePublic::loadFromXML(result); return publicPeer; } catch (zsLib::XML::Exceptions::CheckFailed &) { } return IPeerFilePublicPtr(); }
//--------------------------------------------------------------------- PeerContactProfilePtr PeerContactProfile::createExternalFromPrivateProfile(ElementPtr privateProfileElement) { if (!privateProfileElement) return PeerContactProfilePtr(); privateProfileElement = (privateProfileElement->clone())->toElementChecked(); static const char *contactProfileSkeleton = "<contactProfile version=\"0\">\n" " <private>\n" " <salt />\n" " <proof cipher=\"sha256/aes256\" />\n" " <encryptedProfile cipher=\"sha256/aes256\" />\n" " <contactProfileSecret cipher=\"sha256/aes256\" />\n" " </private>\n" "</contactProfile>"; DocumentPtr contactProfileDoc = Document::create(); contactProfileDoc->parse(contactProfileSkeleton); String contactID = services::IHelper::randomString(32); String contactProfileSecret = services::IHelper::randomString(32); // generate external profile { std::string contactSalt; // generate salt { AutoSeededRandomPool rng; SecureByteBlock contactSaltRaw(32); rng.GenerateBlock(contactSaltRaw, contactSaltRaw.size()); contactSalt = convertToBase64(contactSaltRaw, contactSaltRaw.size()); } ElementPtr contactProfileElement = contactProfileDoc->getFirstChildElementChecked(); contactProfileElement->setAttribute("id", contactID); ElementPtr privateElement = contactProfileElement->getFirstChildElementChecked(); ElementPtr saltElement = privateElement->getFirstChildElementChecked(); TextPtr saltText = Text::create(); saltText->setValue(contactSalt); saltElement->adoptAsLastChild(saltText); SecureByteBlock contactProofHash(32); SHA256 contactProof; contactProof.Update((const BYTE *)"proof:", strlen("proof:")); contactProof.Update((const BYTE *)contactProfileSecret.c_str(), contactProfileSecret.size()); contactProof.Final(contactProofHash); String contactProofInBase64 = convertToBase64(contactProofHash, contactProofHash.size()); ElementPtr proofElement = saltElement->getNextSiblingElementChecked(); TextPtr proofText = Text::create(); proofText->setValue(contactProofInBase64); proofElement->adoptAsLastChild(proofText); DocumentPtr privateProfileDocument = Document::create(); privateProfileDocument->adoptAsLastChild(privateProfileElement); ULONG length = 0; boost::shared_array<char> output; output = privateProfileDocument->write(&length); ElementPtr encryptedProfileElement = proofElement->getNextSiblingElementChecked(); String encryptedProfileString = encryptToBase64("profile", contactProfileSecret, contactSalt, (const BYTE *)(output.get()), length); TextPtr encryptProfileText = Text::create(); encryptProfileText->setValue(encryptedProfileString); encryptedProfileElement->adoptAsLastChild(encryptProfileText); ElementPtr contactProfileSecretElement = encryptedProfileElement->getNextSiblingElementChecked(); TextPtr contactProfileSecretText = Text::create(); contactProfileSecretText->setValue(contactProfileSecret); contactProfileSecretElement->adoptAsLastChild(contactProfileSecretText); } PeerContactProfilePtr pThis(new PeerContactProfile); pThis->mThisWeak = pThis; pThis->mDocument = contactProfileDoc; pThis->mContactProfileSecret = contactProfileSecret; return pThis; }