//--------------------------------------------------------------------- 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; }