From 17e42f1ceb304500e0c2597705ee1a33364cff28 Mon Sep 17 00:00:00 2001 From: drbob Date: Mon, 5 Nov 2012 22:28:08 +0000 Subject: [PATCH] Added core code for pgphash calculations. - Reworked GxsIdGroup members... moved IdType -> groupFlags, so Hash & Sign are only ones. - Reworked GroupServiceString storage. - Added core processing functions - yet to test! git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5777 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/retroshare/rsidentity.h | 20 +- libretroshare/src/serialiser/rsgxsiditems.cc | 26 +- libretroshare/src/services/p3idservice.cc | 764 +++++++++++++++---- libretroshare/src/services/p3idservice.h | 118 ++- libretroshare/src/util/rsid.h | 11 + 5 files changed, 736 insertions(+), 203 deletions(-) diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 13209655b..50dce4257 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -37,6 +37,12 @@ class RsIdentity; extern RsIdentity *rsIdentity; + +// GroupFlags: Only one so far: +#define RSGXSID_GROUPFLAG_REALID 0x0001 + + +// THESE ARE FLAGS FOR INTERFACE. #define RSID_TYPE_MASK 0xff00 #define RSID_RELATION_MASK 0x00ff @@ -61,8 +67,7 @@ class RsGxsIdGroup // In GroupMetaData. //std::string mNickname; (mGroupName) //std::string mKeyId; (mGroupId) - - uint32_t mIdType; + //uint32_t mIdType; (mGroupFlags) // SHA(KeyId + Gpg Fingerprint) -> can only be IDed if GPG known. // The length of the input must be long enough to make brute force search implausible. @@ -70,14 +75,11 @@ class RsGxsIdGroup // Easy to do 1e9 SHA-1 hash computations per second on a GPU. // We will need a minimum of 256 bits, ideally 1024 bits or 2048 bits. - std::string mGpgIdHash; + // Actually PgpIdHash is SHA1(.mMeta.mGroupId + PGPHandler->GpgFingerprint(ownId)) + // ??? 160 bits. - // NOTE: These cannot be transmitted as part of underlying messages.... - // Must use ServiceString. - bool mGpgIdKnown; // if GpgIdHash has been identified. - std::string mGpgId; // if known. - std::string mGpgName; // if known. - std::string mGpgEmail; // if known. + std::string mPgpIdHash; + std::string mPgpIdSign; // Need a signature as proof - otherwise anyone could add others Hashes. }; diff --git a/libretroshare/src/serialiser/rsgxsiditems.cc b/libretroshare/src/serialiser/rsgxsiditems.cc index ebacdc7a1..cc788053f 100644 --- a/libretroshare/src/serialiser/rsgxsiditems.cc +++ b/libretroshare/src/serialiser/rsgxsiditems.cc @@ -120,14 +120,8 @@ RsItem* RsGxsIdSerialiser::deserialise(void* data, uint32_t* size) void RsGxsIdGroupItem::clear() { - group.mGpgIdHash.clear(); - group.mIdType = 0; - - // Others that aren't serialised. - but should be cleared anyway - group.mGpgIdKnown = false; - group.mGpgId.clear(); - group.mGpgName.clear(); - group.mGpgEmail.clear(); + group.mPgpIdHash.clear(); + group.mPgpIdSign.clear(); } std::ostream& RsGxsIdGroupItem::print(std::ostream& out, uint16_t indent) @@ -136,9 +130,9 @@ std::ostream& RsGxsIdGroupItem::print(std::ostream& out, uint16_t indent) uint16_t int_Indent = indent + 2; printIndent(out, int_Indent); - out << "IdType: " << group.mIdType << std::endl; + out << "PgpIdHash: " << group.mPgpIdHash << std::endl; printIndent(out, int_Indent); - out << "GpgIdHash: " << group.mGpgIdHash << std::endl; + out << "PgpIdSign: " << group.mPgpIdSign << std::endl; printRsItemEnd(out ,"RsGxsIdGroupItem", indent); return out; @@ -151,8 +145,8 @@ uint32_t RsGxsIdSerialiser::sizeGxsIdGroupItem(RsGxsIdGroupItem *item) const RsGxsIdGroup& group = item->group; uint32_t s = 8; // header - s += 4; // mIdType. - s += GetTlvStringSize(group.mGpgIdHash); + s += GetTlvStringSize(group.mPgpIdHash); + s += GetTlvStringSize(group.mPgpIdSign); return s; } @@ -185,8 +179,8 @@ bool RsGxsIdSerialiser::serialiseGxsIdGroupItem(RsGxsIdGroupItem *item, void *da offset += 8; /* GxsIdGroupItem */ - ok &= setRawUInt32(data, tlvsize, &offset, item->group.mIdType); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mGpgIdHash); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mPgpIdHash); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mPgpIdSign); if(offset != tlvsize) { @@ -246,8 +240,8 @@ RsGxsIdGroupItem* RsGxsIdSerialiser::deserialiseGxsIdGroupItem(void *data, uint3 /* skip the header */ offset += 8; - ok &= getRawUInt32(data, rssize, &offset, &(item->group.mIdType)); - ok &= GetTlvString(data, rssize, &offset, 1, item->group.mGpgIdHash); + ok &= GetTlvString(data, rssize, &offset, 1, item->group.mPgpIdHash); + ok &= GetTlvString(data, rssize, &offset, 1, item->group.mPgpIdSign); if (offset != rssize) { diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 4d839b2c1..a7fa605f6 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -27,6 +27,10 @@ #include "serialiser/rsgxsiditems.h" #include "util/rsrandom.h" +#include "util/rsstring.h" + +#include "pqi/authgpg.h" + #include #include @@ -44,6 +48,24 @@ RsIdentity *rsIdentity = NULL; +/****** + * Some notes: + * Identity tasks: + * - Provide keys for signing / validating author signatures. + * - Reputations + * - Identify Known Friend's IDs. + * - Provide details to other services (nicknames, reputations, gpg ids, etc) + * + * Background services: + * - Lookup and cache keys / details of identities. + * - Check GPGHashes. + * - Calculate Reputations. + * + * We have a lot of information to store in Service Strings. + * - GPGId or last check ts. + * - Reputation stuff. + */ + #define RSGXSID_MAX_SERVICE_STRING 1024 /********************************************************************************/ @@ -272,6 +294,176 @@ bool p3IdService::createMsg(uint32_t& token, RsGxsIdOpinion &opinion) /************************************************************************************/ /************************************************************************************/ +/* Encoding / Decoding Group Service String stuff + * + * Pgp stuff. + * + * If flagged as pgp id.... + * then we need to know if its been matched, or when we last tried to match. + * + */ + +bool SSGxsIdPgp::load(const std::string &input) +{ + char pgpline[RSGXSID_MAX_SERVICE_STRING]; + int timestamp = 0; + if (1 == sscanf(input.c_str(), "K:1 I:%[^)]", pgpline)) + { + idKnown = true; + pgpId = pgpline; + } + else if (1 == sscanf(input.c_str(), "K:0 T:%d", ×tamp)) + { + lastCheckTs = timestamp; + idKnown = false; + } + else + { + return false; + } + return true; +} + +std::string SSGxsIdPgp::save() const +{ + std::string output; + if (idKnown) + { + output += "K:1 I:"; + output += pgpId; + } + else + { + rs_sprintf(output, "K:0 T:%d", lastCheckTs); + } + return output; +} + +bool SSGxsIdScore::load(const std::string &input) +{ + return (1 == sscanf(input.c_str(), "%d", &score)); +} + +std::string SSGxsIdScore::save() const +{ + std::string output; + rs_sprintf(output, "%d", score); + return output; +} + +bool SSGxsIdCumulator::load(const std::string &input) +{ + return (4 == sscanf(input.c_str(), "%d %d %lf %lf", &count, &nullcount, &sum, &sumsq)); +} + +std::string SSGxsIdCumulator::save() const +{ + std::string output; + rs_sprintf(output, "%d %d %lf %lf", count, nullcount, sum, sumsq); + return output; +} + +bool SSGxsIdGroup::load(const std::string &input) +{ + char pgpstr[RSGXSID_MAX_SERVICE_STRING]; + char scorestr[RSGXSID_MAX_SERVICE_STRING]; + char opinionstr[RSGXSID_MAX_SERVICE_STRING]; + char repstr[RSGXSID_MAX_SERVICE_STRING]; + + // split into two parts. + if (4 != sscanf(input.c_str(), "v1 {%[^}]} {%[^}]} {%[^}]} {%[^}]}", pgpstr, scorestr, opinionstr, repstr)) + { + std::cerr << "SSGxsIdGroup::load() Failed to extract 4 Parts"; + std::cerr << std::endl; + return false; + } + + bool ok = true; + if (0 == strncmp(pgpstr, "P:", 2)) + { + std::cerr << "SSGxsIdGroup::load() pgpstr: " << pgpstr; + std::cerr << std::endl; + ok &= pgp.load(pgpstr); + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid pgpstr: " << pgpstr; + std::cerr << std::endl; + ok = false; + } + + if (0 == strncmp(scorestr, "Y:", 2)) + { + std::cerr << "SSGxsIdGroup::load() scorestr: " << scorestr; + std::cerr << std::endl; + ok &= score.load(scorestr); + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid scorestr: " << scorestr; + std::cerr << std::endl; + ok = false; + } + + if (0 == strncmp(opinionstr, "O:", 2)) + { + std::cerr << "SSGxsIdGroup::load() opinionstr: " << opinionstr; + std::cerr << std::endl; + ok &= opinion.load(opinionstr); + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid opinionstr: " << opinionstr; + std::cerr << std::endl; + ok = false; + } + + if (0 == strncmp(repstr, "R:", 2)) + { + std::cerr << "SSGxsIdGroup::load() repstr: " << repstr; + std::cerr << std::endl; + ok &= reputation.load(repstr); + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid repstr: " << repstr; + std::cerr << std::endl; + ok = false; + } + + return ok; +} + +std::string SSGxsIdGroup::save() const +{ + std::string output = "v1 "; + + output += "{P:"; + output += pgp.save(); + output += "}"; + + output += "{Y:"; + output += score.save(); + output += "}"; + + output += "{O:"; + output += opinion.save(); + output += "}"; + + output += "{R:"; + output += reputation.save(); + output += "}"; + + std::cerr << "SSGxsIdGroup::save() output: " << output; + std::cerr << std::endl; + + return output; +} + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + /* Cache of recently used keys * * It is expensive to fetch the keys, so we want to keep them around if possible. @@ -727,6 +919,403 @@ bool p3IdService::cachetest_request() return true; } +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* Task to determine GPGHash matches + * + * Info to be stored in GroupServiceString + Cache. + * + * Actually - it must be a Signature here - otherwise, you could + * put in a hash from someone else! + * + * Don't think that we need to match very often - maybe once a day? + * Actually - we should scale the matching based on number of keys we have. + * + * imagine - 10^6 rsa keys + 10^3 gpg keys => 10^9 combinations. + * -- far too many to check all quickly. + * + * Need to grab and cache data we need... then check over slowly. + * + * maybe grab a list of all gpgids - that we know of: store id list. + * then big GroupRequest, and iterate through these. + **/ + +//const int SHA_DIGEST_LENGTH = 20; + +typedef t_RsGenericIdType GxsIdPgpHash; + +static void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdPgpHash &hash); + + +void p3IdService::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) +{ + RsGxsIdGroupItem *item = dynamic_cast(grpItem); + if (!item) + { + std::cerr << "p3IdService::service_CreateGroup() ERROR invalid cast"; + std::cerr << std::endl; + return; + } + + std::cerr << "p3IdService::service_CreateGroup() for : " << item->group.mMeta.mGroupId; + std::cerr << std::endl; + + if (item->group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + /* create the hash */ + GxsIdPgpHash hash; + + /* */ + PGPFingerprintType ownFinger; + PGPIdType ownId(AuthGPG::getAuthGPG()->getGPGOwnId()); + + if (!AuthGPG::getAuthGPG()->getKeyFingerprint(ownId,ownFinger)) + { + std::cerr << "p3IdService::service_CreateGroup() ERROR Own Finger is stuck"; + std::cerr << std::endl; + return; // abandon attempt! + } + + calcPGPHash(item->group.mMeta.mGroupId, ownFinger, hash); + item->group.mPgpIdHash = hash.toStdString(); + + /* do signature */ + +#define MAX_SIGN_SIZE 2048 + uint8_t signarray[MAX_SIGN_SIZE]; + unsigned int sign_size = MAX_SIGN_SIZE; + if (!AuthGPG::getAuthGPG()->SignDataBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, signarray, &sign_size)) + { + /* error */ + std::cerr << "p3IdService::service_CreateGroup() ERROR Signing stuff"; + std::cerr << std::endl; + } + else + { + /* push binary into string -> really bad! */ + item->group.mPgpIdSign = ""; + for(unsigned int i = 0; i < sign_size; i++) + { + item->group.mPgpIdSign += signarray[i]; + } + } + /* done! */ + } +} + + + + +bool p3IdService::pgphash_tick() +{ + /* every minute - run a background check */ + time_t now = time(NULL); + bool doHash = false; + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + if (now - mHashPgp_LastTs > TEST_PERIOD) + { + doHash = true; + mHashPgp_LastTs = now; + } + } + + if (doHash) + { + std::cerr << "p3IdService::pgphash_tick() starting"; + std::cerr << std::endl; + pgphash_getlist(); + } + + pgphash_request(); + pgphash_process(); + + return true; +} + +bool p3IdService::pgphash_getlist() +{ + + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + if (mHashPgp_Active) + { + std::cerr << "p3IdService::cachetest_getlist() Already active"; + std::cerr << std::endl; + return false; + } + } + + std::cerr << "p3IdService::cachetest_getlist() making request"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mHashPgp_Token = token; + mHashPgp_Active = true; + } + return true; +} + + +bool p3IdService::pgphash_request() +{ + uint32_t token = 0; + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + if (!mHashPgp_Active) + { + return false; + } + token = mHashPgp_Token; + } + + std::cerr << "p3IdService::pgphash_request() checking request"; + std::cerr << std::endl; + + uint32_t status = RsGenExchange::getTokenService()->requestStatus(token); + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::cerr << "p3IdService::pgphash_request() token ready: " << token; + std::cerr << std::endl; + + // We need full data - for access to Hash & Signature. + // Perhaps we will change this to an initial pass through Meta, + // and use this to discard lots of things. + + // Even better - we can set flags in the Meta Data, (IdType), + // And use GXS to filter out all the AnonIds, and only have to process + // Proper Ids. + + // We Will do this later! + + std::vector groups; + std::vector groupsToProcess; + bool ok = getGroupData(token, groups); + + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mHashPgp_Active = false; + } + + if(ok) + { + std::vector::iterator vit; + for(vit = groups.begin(); vit != groups.end(); vit++) + { + /* Filter based on IdType */ + if (!(vit->mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID)) + { + std::cerr << "p3IdService::pgphash_request() discarding AnonID"; + std::cerr << std::endl; + continue; + } + + /* now we need to decode the Service String - see what is saved there */ + SSGxsIdGroup ssdata; + if (ssdata.load(vit->mMeta.mServiceString)) + { + if (ssdata.pgp.idKnown) + { + std::cerr << "p3IdService::pgphash_request() discarding Already Known"; + std::cerr << std::endl; + continue; + } + + /* Have a linear attempt policy - + * if zero checks - try now. + * if 1 check, at least a day. + * if 2 checks: 2days, etc. + */ + +#define SECS_PER_DAY (3600 * 24) + time_t age = time(NULL) - ssdata.pgp.lastCheckTs; + time_t wait_period = ssdata.pgp.checkAttempts * SECS_PER_DAY; + if (wait_period > 30 * SECS_PER_DAY) + { + wait_period = 30 * SECS_PER_DAY; + } + + if (age < wait_period) + { + std::cerr << "p3IdService::pgphash_request() discarding Recently Check"; + std::cerr << std::endl; + continue; + } + } + + /* if we get here -> then its to be processed */ + std::cerr << "p3IdService::cachetest_request() Requested Key Id: " << *vit; + std::cerr << std::endl; + + mGroupsToProcess.push_back(*vit); + } + } + } + return true; +} + +bool p3IdService::pgphash_process() +{ + /* each time this is called - process one Id from mGroupsToProcess */ + if (mGroupsToProcess.empty()) + { + return true; + } + + RsGxsIdGroup pg = mGroupsToProcess.front(); + mGroupsToProcess.pop_front(); + + SSGxsIdGroup ssdata; + ssdata.load(pg.mMeta.mServiceString); // attempt load - okay if fails. + + PGPIdType pgpId; + + if (checkId(pg, pgpId)) + { + /* found a match - update everything */ + /* Consistency issues here - what if Reputation was recently updated? */ + + + /* update */ + ssdata.pgp.idKnown = true; + ssdata.pgp.pgpId = pgpId.toStdString(); + +// SHOULD BE PUSHED TO CACHE! +#if 0 + id.mGpgIdKnown = true; + + id.mGpgId = *it; + id.mGpgName = details.name; + id.mGpgEmail = details.email; + + if (*it == ownId) + { + id.mIdType |= RSID_RELATION_YOURSELF; + } + else if (rsPeers->isGPGAccepted(*it)) + { + id.mIdType |= RSID_RELATION_FRIEND; + } + else + { + id.mIdType |= RSID_RELATION_OTHER; + } + +#endif + + } + else + { + ssdata.pgp.lastCheckTs = time(NULL); + ssdata.pgp.checkAttempts++; + } + + /* set new Group ServiceString */ + uint32_t dummyToken = 0; + std::string serviceString = ssdata.save(); + setGroupServiceString(dummyToken, pg.mMeta.mGroupId, serviceString); + + return true; + +} + + + +bool p3IdService::checkId(const RsGxsIdGroup &grp, PGPIdType &pgpId) +{ + std::cerr << "p3IdService::checkId() Starting Match Check for RsGxsId: "; + std::cerr << grp.mMeta.mGroupId; + std::cerr << std::endl; + + /* iterate through and check hash */ + GxsIdPgpHash ans(grp.mPgpIdHash); + + std::map::iterator mit; + for(mit = mPgpFingerprintMap.begin(); mit != mPgpFingerprintMap.end(); mit++) + { + GxsIdPgpHash hash; + calcPGPHash(grp.mMeta.mGroupId, mit->second, hash); + if (ans == hash) + { + std::cerr << "p3IdService::checkId() HASH MATCH!"; + std::cerr << std::endl; + + /* miracle match! */ + /* check signature too */ + if (AuthGPG::getAuthGPG()->VerifySignBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, + (unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(), + mit->second.toStdString())) + { + std::cerr << "p3IdService::checkId() Signature Okay too!"; + std::cerr << std::endl; + + pgpId = mit->first; + return true; + } + + /* error */ + std::cerr << "p3IdService::checkId() ERROR Signature Failed"; + std::cerr << std::endl; + } + } + + std::cerr << "p3IdService::checkId() Checked " << mPgpFingerprintMap.size() << " Hashes without Match"; + std::cerr << std::endl; + + return false; +} + + +/* worker functions */ +void p3IdService::getPgpIdList() +{ + std::cerr << "p3IdService::getPgpIdList() Starting...."; + std::cerr << std::endl; + + std::list list; + AuthGPG::getAuthGPG()->getGPGFilteredList(list); + + std::list::iterator it; + for(it = list.begin(); it != list.end(); it++) + { + PGPIdType pgpId(*it); + PGPFingerprintType fp; + AuthGPG::getAuthGPG()->getKeyFingerprint(pgpId, fp); + + mPgpFingerprintMap[pgpId] = fp; + } + + std::cerr << "p3IdService::getPgpIdList() Items: " << mPgpFingerprintMap.size(); + std::cerr << std::endl; +} + + +void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdPgpHash &hash) +{ + unsigned char signature[SHA_DIGEST_LENGTH]; + /* hash id + pubkey => pgphash */ + SHA_CTX *sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + + SHA1_Update(sha_ctx, id.c_str(), id.length()); // TO FIX ONE DAY. + SHA1_Update(sha_ctx, pgp.toByteArray(), pgp.SIZE_IN_BYTES); + SHA1_Final(signature, sha_ctx); + hash = GxsIdPgpHash(signature); + + delete sha_ctx; +} + /************************************************************************************/ /************************************************************************************/ @@ -773,8 +1362,9 @@ void p3IdService::generateDummyData() //id.mKeyId = genRandomId(); id.mMeta.mGroupId = genRandomId(); - id.mIdType = RSID_TYPE_REALID; - id.mGpgIdHash = genRandomId(); + id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; + id.mPgpIdHash = genRandomId(); + id.mPgpIdSign = genRandomId(); if (rsPeers->getPeerDetails(*it, details)) { @@ -783,36 +1373,16 @@ void p3IdService::generateDummyData() //id.mNickname = out.str(); id.mMeta.mGroupName = out.str(); - - id.mGpgIdKnown = true; - id.mGpgId = *it; - id.mGpgName = details.name; - id.mGpgEmail = details.email; - - if (*it == ownId) - { - id.mIdType |= RSID_RELATION_YOURSELF; - } - else if (rsPeers->isGPGAccepted(*it)) - { - id.mIdType |= RSID_RELATION_FRIEND; - } - else - { - id.mIdType |= RSID_RELATION_OTHER; - } - + } else { std::cerr << "p3IdService::generateDummyData() missing" << std::endl; std::cerr << std::endl; - id.mIdType |= RSID_RELATION_OTHER; //id.mNickname = genRandomId(); id.mMeta.mGroupName = genRandomId(); - id.mGpgIdKnown = false; } uint32_t dummyToken = 0; @@ -841,22 +1411,13 @@ void p3IdService::generateDummyData() RsPeerDetails details; - //id.mKeyId = genRandomId(); - id.mMeta.mGroupId = genRandomId(); - id.mIdType = RSID_TYPE_REALID; - id.mGpgIdHash = genRandomId(); - - id.mIdType |= RSID_RELATION_OTHER; - //id.mNickname = genRandomId(); id.mMeta.mGroupName = genRandomId(); - id.mGpgIdKnown = false; - id.mGpgId = ""; - id.mGpgName = ""; - id.mGpgEmail = ""; - //mIds[id.mKeyId] = id; - //mIdProxy->addGroup(id); - // STORE + id.mMeta.mGroupId = genRandomId(); + id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; + id.mPgpIdHash = genRandomId(); + id.mPgpIdSign = genRandomId(); + uint32_t dummyToken = 0; createGroup(dummyToken, id); } @@ -868,21 +1429,14 @@ void p3IdService::generateDummyData() RsPeerDetails details; - //id.mKeyId = genRandomId(); - id.mMeta.mGroupId = genRandomId(); - id.mIdType = RSID_TYPE_PSEUDONYM; - id.mGpgIdHash = ""; - - //id.mNickname = genRandomId(); id.mMeta.mGroupName = genRandomId(); - id.mGpgIdKnown = false; - id.mGpgId = ""; - id.mGpgName = ""; - id.mGpgEmail = ""; - //mIds[id.mKeyId] = id; - //mIdProxy->addGroup(id); - // STORE + id.mMeta.mGroupId = genRandomId(); + id.mMeta.mGroupFlags = 0; + id.mPgpIdHash = ""; + id.mPgpIdSign = ""; + + uint32_t dummyToken = 0; createGroup(dummyToken, id); } @@ -1291,10 +1845,8 @@ bool p3IdService::background_processNewMessages() mit->second.mGroupStatus |= ID_LOCAL_STATUS_INC_CALC_FLAG; - std::string serviceString; - IdGroupServiceStrData ssData; - - if (!extractIdGroupCache(serviceString, ssData)) + SSGxsIdGroup ssdata; + if (!ssdata.load(mit->second.mServiceString)) { /* error */ std::cerr << "p3IdService::background_processNewMessages() ERROR Extracting"; @@ -1308,8 +1860,9 @@ bool p3IdService::background_processNewMessages() /* store it back in */ std::cerr << "p3IdService::background_processNewMessages() Stored: "; std::cerr << std::endl; - - if (!encodeIdGroupCache(serviceString, ssData)) + + std::string serviceString = ssdata.save(); + if (0) { /* error */ std::cerr << "p3IdService::background_processNewMessages() ERROR Storing"; @@ -1365,75 +1918,6 @@ bool p3IdService::background_processNewMessages() } -bool p3IdService::encodeIdGroupCache(std::string &str, const IdGroupServiceStrData &data) -{ - char line[RSGXSID_MAX_SERVICE_STRING]; - - snprintf(line, RSGXSID_MAX_SERVICE_STRING, "v1 {%s} {Y:%d O:%d %d %f %f R:%d %d %f %f}", - data.pgpId.c_str(), data.ownScore, - data.opinion.count, data.opinion.nullcount, data.opinion.sum, data.opinion.sumsq, - data.reputation.count, data.reputation.nullcount, data.reputation.sum, data.reputation.sumsq); - - str = line; - return true; -} - - -bool p3IdService::extractIdGroupCache(std::string &str, IdGroupServiceStrData &data) -{ - char pgpline[RSGXSID_MAX_SERVICE_STRING]; - char scoreline[RSGXSID_MAX_SERVICE_STRING]; - - uint32_t iOwnScore; - IdRepCumulScore iOpin; - IdRepCumulScore iRep; - - // split into two parts. - if (2 != sscanf(str.c_str(), "v1 {%[^}]} {%[^}]", pgpline, scoreline)) - { - std::cerr << "p3IdService::extractIdGroupCache() Failed to extract Two Parts"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3IdService::extractIdGroupCache() pgpline: " << pgpline; - std::cerr << std::endl; - std::cerr << "p3IdService::extractIdGroupCache() scoreline: " << scoreline; - std::cerr << std::endl; - - std::string pgptmp = pgpline; - if (pgptmp.length() > 5) - { - std::cerr << "p3IdService::extractIdGroupCache() Believe to have pgpId: " << pgptmp; - std::cerr << std::endl; - data.pgpIdKnown = true; - data.pgpId = pgptmp; - } - else - { - std::cerr << "p3IdService::extractIdGroupCache() Think pgpId Invalid"; - std::cerr << std::endl; - data.pgpIdKnown = false; - } - - - if (9 == sscanf(scoreline, " Y:%d O:%d %d %lf %lf R:%d %d %lf %lf", &iOwnScore, - &(iOpin.count), &(iOpin.nullcount), &(iOpin.sum), &(iOpin.sumsq), - &(iRep.count), &(iRep.nullcount), &(iRep.sum), &(iRep.sumsq))) - { - data.ownScore = iOwnScore; - data.opinion = iOpin; - data.reputation = iRep; - return true; - } - - std::cerr << "p3IdService::extractIdGroupCache() Failed to extract scores"; - std::cerr << std::endl; - - return false; -} - - bool p3IdService::background_FullCalcRequest() { @@ -1583,23 +2067,14 @@ bool p3IdService::background_processFullCalc() if (validmsgs) { - std::string serviceString; - IdGroupServiceStrData ssData; - - - if (!encodeIdGroupCache(serviceString, ssData)) - { - std::cerr << "p3IdService::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3IdService::background_updateVoteCounts() Encoded String: " << serviceString; - std::cerr << std::endl; - /* store new result */ - uint32_t dummyToken = 0; - setGroupServiceString(dummyToken, groupId, serviceString); - } + SSGxsIdGroup ssdata; + std::string serviceString = ssdata.save(); + + std::cerr << "p3IdService::background_updateVoteCounts() Encoded String: " << serviceString; + std::cerr << std::endl; + /* store new result */ + uint32_t dummyToken = 0; + setGroupServiceString(dummyToken, groupId, serviceString); } { @@ -1633,9 +2108,8 @@ bool p3IdService::background_cleanup() std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &grp) { out << "RsGxsIdGroup: Meta: " << grp.mMeta; - out << " IdType: " << grp.mIdType << " GpgIdHash: " << grp.mGpgIdHash; - out << "(((Unusable: ( GpgIdKnown: " << grp.mGpgIdKnown << " GpgId: " << grp.mGpgId; - out << " GpgName: " << grp.mGpgName << " GpgEmail: " << grp.mGpgEmail << ") )))"; + out << " PgpIdHash: " << grp.mPgpIdHash; + out << " PgpIdSign: [binary]"; // << grp.mPgpIdSign; out << std::endl; return out; diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index 593cf3fbf..19ef8d315 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -36,6 +36,8 @@ #include "util/rsmemcache.h" +#include "pqi/authgpg.h" + /* * Identity Service * @@ -43,9 +45,52 @@ // INTERNAL DATA TYPES. // Describes data stored in GroupServiceString. -class IdRepCumulScore + +class SSBit +{ + public: +virtual bool load(const std::string &input) = 0; +virtual std::string save() const = 0; +}; + + + +class SSGxsIdPgp: public SSBit +{ + public: + SSGxsIdPgp() + :idKnown(false), lastCheckTs(0), checkAttempts(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + bool idKnown; + time_t lastCheckTs; + uint32_t checkAttempts; + std::string pgpId; +}; + +class SSGxsIdScore: public SSBit +{ + public: + SSGxsIdScore() + :score(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + int score; +}; + +class SSGxsIdCumulator: public SSBit { public: + SSGxsIdCumulator() + :count(0), nullcount(0), sum(0), sumsq(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + uint32_t count; uint32_t nullcount; double sum; @@ -54,17 +99,21 @@ public: // derived parameters: }; - -class IdGroupServiceStrData +class SSGxsIdGroup: public SSBit { public: - IdGroupServiceStrData() { pgpIdKnown = false; } - bool pgpIdKnown; - std::string pgpId; - - uint32_t ownScore; - IdRepCumulScore opinion; - IdRepCumulScore reputation; + SSGxsIdGroup() { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + // pgphash status + SSGxsIdPgp pgp; + + // reputation score. + SSGxsIdScore score; + SSGxsIdCumulator opinion; + SSGxsIdCumulator reputation; }; @@ -72,7 +121,6 @@ public: #define ID_LOCAL_STATUS_INC_CALC_FLAG 0x00020000 - #define MAX_CACHE_SIZE 100 // Small for testing.. //#define MAX_CACHE_SIZE 10000 // More useful size @@ -104,9 +152,7 @@ class LruData // Not sure exactly what should be inherited here? // Chris - please correct as necessary. -class p3IdService: - public RsGxsIdExchange, - public RsIdentity +class p3IdService: public RsGxsIdExchange, public RsIdentity { public: p3IdService(RsGeneralDataService* gds, RsNetworkExchangeService* nes); @@ -164,8 +210,11 @@ virtual bool getReputation(const RsGxsId &id, const GixsReputation &rep); protected: - /** Notifications **/ - virtual void notifyChanges(std::vector& changes); + /** Notifications **/ +virtual void notifyChanges(std::vector& changes); + + /** Overloaded to add PgpIdHash to Group Definition **/ +virtual void service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); private: @@ -175,14 +224,6 @@ virtual bool getReputation(const RsGxsId &id, const GixsReputation &rep); */ int cache_tick(); - - //bool cache_is_loaded(const RsGxsId &id); - //bool cache_fetch(const RsGxsId &key, RsGxsIdCache &data); - - //bool cache_store(const RsGxsIdGroup &group); - //bool cache_resize(); - //bool cache_discard_LRU(int count_to_clear); - bool cache_request_load(const RsGxsId &id); bool cache_start_load(); bool cache_check_loading(); @@ -190,12 +231,6 @@ virtual bool getReputation(const RsGxsId &id, const GixsReputation &rep); bool cache_store(const RsGxsIdGroupItem *item); - /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ - //bool locked_cache_update_lrumap(const RsGxsId &key, time_t old_ts, time_t new_ts); - //std::map mCacheDataMap; - //std::multimap mCacheLruMap; - //uint32_t mCacheDataCount; - time_t mCacheLoad_LastCycle; int mCacheLoad_Status; std::list mCacheLoad_ToCache; @@ -220,6 +255,26 @@ virtual bool getReputation(const RsGxsId &id, const GixsReputation &rep); bool mCacheTest_Active; uint32_t mCacheTest_Token; +/************************************************************************ + * pgphash processing. + * + */ + bool pgphash_tick(); + bool pgphash_getlist(); + bool pgphash_request(); + bool pgphash_process(); + + bool checkId(const RsGxsIdGroup &grp, PGPIdType &pgp_id); + void getPgpIdList(); + /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ + + time_t mHashPgp_LastTs; + bool mHashPgp_Active; + uint32_t mHashPgp_Token; + + std::map mPgpFingerprintMap; + std::list mGroupsToProcess; + /************************************************************************ * Below is the background task for processing opinions => reputations * @@ -239,9 +294,6 @@ std::string genRandomId(); bool background_cleanup(); - bool encodeIdGroupCache(std::string &str, const IdGroupServiceStrData &data); - bool extractIdGroupCache(std::string &str, IdGroupServiceStrData &data); - RsMutex mIdMtx; /***** below here is locked *****/ diff --git a/libretroshare/src/util/rsid.h b/libretroshare/src/util/rsid.h index 464999a5d..bd1343fcb 100644 --- a/libretroshare/src/util/rsid.h +++ b/libretroshare/src/util/rsid.h @@ -25,6 +25,9 @@ // Warning: never store references to a t_RsGenericIdType accross threads, since the // cached string convertion is not thread safe. // + +#pragma once + #include #include @@ -60,6 +63,14 @@ template class t_RsGenericIdType return !operator==(fp) ; } + bool operator<(const t_RsGenericIdType& fp) const + { + for(uint32_t i=0;i