//--------------------------------------------------------------------- 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(); }
//--------------------------------------------------------------------- bool PeerContactProfile::usesContactProfileSecret(const char *contactProfileSecret) { AutoRecursiveLock lock(mLock); if (NULL == contactProfileSecret) return false; if (!mDocument) return false; try { ElementPtr contactProfileElement = getContactProfileElement(); if (!contactProfileElement) return false; ElementPtr proofElement = contactProfileElement->findFirstChildElementChecked("private")->findFirstChildElementChecked("proof"); String proofAsBase64 = proofElement->getText(true); SecureByteBlock proofHash; convertFromBase64(proofAsBase64, proofHash); SecureByteBlock calculatedProofHash(32); if (calculatedProofHash.size() != proofHash.size()) return false; SHA256 shaProof; shaProof.Update((const BYTE *)"proof:", strlen("proof:")); shaProof.Update((const BYTE *)contactProfileSecret, strlen(contactProfileSecret)); shaProof.Final(calculatedProofHash); if (0 != memcmp(calculatedProofHash, proofHash, proofHash.size())) return false; // this is the secret and it is verified mContactProfileSecret = contactProfileSecret; } catch (zsLib::XML::Exceptions::CheckFailed &) { return false; } return true; }
//--------------------------------------------------------------------- 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(); }
//--------------------------------------------------------------------- void PeerContactProfile::internalTemporaryGetContactProfileSecret() { if (!mDocument) return; try { ElementPtr contactProfileElement = getContactProfileElement(); if (!contactProfileElement) return; ElementPtr privateElement = contactProfileElement->findFirstChildElementChecked("private"); ElementPtr contactProfileSecretElement = privateElement->findFirstChildElementChecked("contactProfileSecret"); String cotactProfileSecret = contactProfileSecretElement->getText(); if (cotactProfileSecret.isEmpty()) return; mContactProfileSecret = cotactProfileSecret; } catch (zsLib::XML::Exceptions::CheckFailed &) { } }
//--------------------------------------------------------------------- bool PeerContactProfile::setPrivateProfile(ElementPtr newProfileElement) { AutoRecursiveLock lock(mLock); if (!mDocument) return false; PeerFilesPtr outer; IPeerFilePrivatePtr privatePeer; if (!isExternal()) { outer = mPeerFiles.lock(); if (!outer) return false; privatePeer = outer->getPrivate(); if (!privatePeer) return false; } try { ElementPtr contactProfileElement = getContactProfileElement(); if (!contactProfileElement) return false; ElementPtr privateElement = contactProfileElement->findFirstChildElementChecked("private"); ElementPtr encryptedProfileElement = privateElement->findFirstChildElement("encryptedProfile"); ElementPtr saltElement = privateElement->findFirstChildElementChecked("salt"); String saltAsBase64 = saltElement->getText(true); if (!newProfileElement) { // erasing the profile element to clean newProfileElement = Element::create(); newProfileElement->setValue("profile"); } DocumentPtr tempDoc = Document::create(); tempDoc->adoptAsLastChild(newProfileElement->clone()); // write out the new value boost::shared_array<char> output = tempDoc->write(); // encrypt it String encryptedProfileAsBase64 = encryptToBase64( "profile", mContactProfileSecret.c_str(), saltAsBase64, (const BYTE *)(output.get()), strlen(output.get()) ); ElementPtr tempNewEncryptedProfileElement = Element::create(); tempNewEncryptedProfileElement->setValue("encryptedProfile"); TextPtr encryptedProfileText = Text::create(); encryptedProfileText->setValue(encryptedProfileAsBase64); tempNewEncryptedProfileElement->adoptAsLastChild(encryptedProfileText); if (encryptedProfileElement) { encryptedProfileElement->adoptAsNextSibling(tempNewEncryptedProfileElement); encryptedProfileElement->orphan(); } else { privateElement->adoptAsLastChild(tempNewEncryptedProfileElement); } // upgrade the document version number UINT version = getVersionNumber(); ++version; contactProfileElement->setAttribute("version", Stringize<UINT>(version).string()); if (!isExternal()) { // now this this must be signed privatePeer->signElement(contactProfileElement); } } catch (zsLib::XML::Exceptions::CheckFailed &) { return false; } return true; }