mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-13 08:29:32 -05:00
improved GxsId signature checking scheme to avoid bruteforcing PGPHash when signature provides the issuer ID
This commit is contained in:
parent
17b2da269a
commit
a7918d426e
@ -3886,9 +3886,7 @@ bool p3IdService::pgphash_process()
|
||||
#endif // DEBUG_IDS
|
||||
}
|
||||
else
|
||||
{
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDone)
|
||||
@ -3960,7 +3958,14 @@ bool p3IdService::pgphash_process()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// This method allows to have a null issuer ID in the signature, in which case the signature is anonymous.
|
||||
// The correct PGP key to check is looked for by bruteforcing
|
||||
//
|
||||
// grp.mPgpIdHash == SHA1( GroupId | PgpFingerPrint )
|
||||
//
|
||||
// For now, this is probably never used because signed IDs use a clear signature. The advntage of hiding the
|
||||
// ID has not been clearly demonstrated anyway, which allows to directly look for the ID in the list of
|
||||
// known keys instead of computing tons of hashes.
|
||||
|
||||
bool p3IdService::checkId(const RsGxsIdGroup &grp, RsPgpId &pgpId,bool& error)
|
||||
{
|
||||
@ -3980,99 +3985,97 @@ bool p3IdService::checkId(const RsGxsIdGroup &grp, RsPgpId &pgpId,bool& error)
|
||||
#endif // DEBUG_IDS
|
||||
|
||||
/* iterate through and check hash */
|
||||
Sha1CheckSum ans = grp.mPgpIdHash;
|
||||
|
||||
Sha1CheckSum hash;
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::string esign ;
|
||||
Radix64::encode((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),esign) ;
|
||||
std::cerr << "Checking group signature " << esign << std::endl;
|
||||
#endif
|
||||
RsPgpId issuer_id ;
|
||||
RsPgpFingerprint pgp_fingerprint;
|
||||
pgpId.clear() ;
|
||||
|
||||
if(mPgpUtils->parseSignature((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),issuer_id))
|
||||
if(mPgpUtils->parseSignature((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),issuer_id) && !issuer_id.isNull())
|
||||
{
|
||||
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
|
||||
pgpId = issuer_id ;
|
||||
|
||||
auto mit = mPgpFingerprintMap.find(issuer_id);
|
||||
|
||||
if(mit == mPgpFingerprintMap.end())
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "Issuer found: " << issuer_id << std::endl;
|
||||
std::cerr << "Issuer Id: " << issuer_id << " is not known. Key will be marked as non verified." << std::endl;
|
||||
#endif
|
||||
pgpId = issuer_id ;
|
||||
error = false;
|
||||
return false;
|
||||
}
|
||||
calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash);
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "Issuer from PGP signature: " << issuer_id << " is known. Computed corresponding hash: " << hash << std::endl;
|
||||
#endif
|
||||
if(grp.mPgpIdHash != hash)
|
||||
{
|
||||
std::cerr << "(EE) Unexpected situation: GxsId signature hash (" << hash << ") doesn't correspond to what's listed in the mPgpIdHash field (" << grp.mPgpIdHash << ")." << std::endl;
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
pgp_fingerprint = mit->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Signature parsing failed!!" << std::endl;
|
||||
pgpId.clear() ;
|
||||
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "Bruteforcing PGP hash from GxsId mPgpHash: " << grp.mPgpIdHash << std::endl;
|
||||
#endif
|
||||
for(auto mit = mPgpFingerprintMap.begin(); mit != mPgpFingerprintMap.end(); ++mit)
|
||||
{
|
||||
calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash);
|
||||
|
||||
std::cerr << " profile key " << mit->first << " (" << mit->second << ") : ";
|
||||
|
||||
if (grp.mPgpIdHash == hash)
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "MATCH!" << std::endl;
|
||||
#endif
|
||||
pgpId = mit->first;
|
||||
pgp_fingerprint = mit->second;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_IDS
|
||||
else
|
||||
std::cerr << "fails" << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Look for the PGP id given by the signature
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "\tExpected Answer: " << ans.toStdString();
|
||||
std::cerr << std::endl;
|
||||
#endif // DEBUG_IDS
|
||||
|
||||
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<RsPgpId, PGPFingerprintType>::iterator mit;
|
||||
for(mit = mPgpFingerprintMap.begin(); mit != mPgpFingerprintMap.end(); ++mit)
|
||||
{
|
||||
Sha1CheckSum hash;
|
||||
calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash);
|
||||
|
||||
|
||||
if (ans == hash)
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::checkId() HASH MATCH!";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "p3IdService::checkId() Hash : " << hash.toStdString();
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Now checking the signature: ";
|
||||
#endif
|
||||
|
||||
/* miracle match! */
|
||||
/* check signature too */
|
||||
if (mPgpUtils->VerifySignBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES,
|
||||
(unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),
|
||||
mit->second))
|
||||
{
|
||||
if (mPgpUtils->VerifySignBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, (unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(), pgp_fingerprint))
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::checkId() Signature Okay too!";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " Signature validates!" << std::endl;
|
||||
#endif
|
||||
|
||||
pgpId = mit->first;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* error */
|
||||
std::cerr << "p3IdService::checkId() ERROR Signature Failed";
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "p3IdService::checkId() Matched PGPID: " << mit->first.toStdString();
|
||||
std::cerr << " Fingerprint: " << mit->second.toStdString();
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "p3IdService::checkId() Signature: ";
|
||||
std::string strout;
|
||||
|
||||
/* push binary into string -> really bad! */
|
||||
for(unsigned int i = 0; i < grp.mPgpIdSign.length(); i++)
|
||||
{
|
||||
rs_sprintf_append(strout, "%02x", (uint32_t) ((uint8_t) grp.mPgpIdSign[i]));
|
||||
}
|
||||
std::cerr << strout;
|
||||
std::cerr << std::endl;
|
||||
|
||||
error = true ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
error = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::checkId() Checked " << mPgpFingerprintMap.size() << " Hashes without Match";
|
||||
std::cerr << std::endl;
|
||||
#endif // DEBUG_IDS
|
||||
|
||||
return false;
|
||||
std::cerr << " Signature fails!" << std::endl;
|
||||
#endif
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* worker functions */
|
||||
void p3IdService::getPgpIdList()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user