From 1b58ef74f86b7b941d9d27aa389630bf64e79f8f Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 15 Jun 2012 21:58:46 +0000 Subject: [PATCH] implemented efficient signature merging. Not fully tested yet! git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-OpenPGP@5223 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/pgp/pgphandler.cc | 79 +++++++++++++++++++++++++++-- libretroshare/src/pgp/pgphandler.h | 1 + libretroshare/src/util/pgpkey.cc | 10 ++-- libretroshare/src/util/pgpkey.h | 4 ++ openpgpsdk/src/keyring.c | 9 +--- 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc index 7486fcfa1..07121766d 100644 --- a/libretroshare/src/pgp/pgphandler.cc +++ b/libretroshare/src/pgp/pgphandler.cc @@ -17,6 +17,7 @@ extern "C" { #include "pgphandler.h" #include "retroshare/rsiface.h" // For rsicontrol. #include "util/rsdir.h" // For rsicontrol. +#include "util/pgpkey.h" // For rsicontrol. PassphraseCallback PGPHandler::_passphrase_callback = NULL ; @@ -417,6 +418,8 @@ void PGPHandler::addNewKeyToOPSKeyring(ops_keyring_t *kr,const ops_keydata_t& ke bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,PGPIdType& id,std::string& error_string) { + std::cerr << "Reading new key from string: " << std::endl; + ops_keyring_t *tmp_keyring = allocateOPSKeyring(); ops_memory_t *mem = ops_memory_new() ; ops_memory_add(mem,(unsigned char *)pgp_cert.c_str(),pgp_cert.length()) ; @@ -436,7 +439,7 @@ bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,PGPIdType free(mem) ; error_string.clear() ; - std::cerr << "Key read correctly: " << std::endl; + std::cerr << " Key read correctly: " << std::endl; ops_keyring_list(tmp_keyring) ; const ops_keydata_t *keydata = NULL ; @@ -446,12 +449,29 @@ bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,PGPIdType { id = PGPIdType(keydata->key_id) ; - addNewKeyToOPSKeyring(_pubring,*keydata) ; + std::cerr << " id: " << id.toStdString() << std::endl; + + // See if the key is already in the keyring + const ops_keydata_t *existing_key ; + std::map::const_iterator res = _public_keyring_map.find(id.toStdString()) ; + + if(res == _public_keyring_map.end() || (existing_key = ops_keyring_get_key_by_index(_pubring,res->second._key_index)) == NULL) + { + std::cerr << " Key is new. Adding it to keyring" << std::endl; + addNewKeyToOPSKeyring(_pubring,*keydata) ; // the key is new. + } + else + { + std::cerr << " Key exists. Merging signatures." << std::endl; + if(mergeKeySignatures(const_cast(existing_key),keydata) ) + _pubring_changed = true ; + } + initCertificateInfo(_public_keyring_map[id.toStdString()],keydata,_pubring->nkeys-1) ; validateAndUpdateSignatures(_public_keyring_map[id.toStdString()],keydata) ; } - std::cerr << "Added the key in the main public keyring." << std::endl; + std::cerr << " Added the key in the main public keyring." << std::endl; ops_keyring_free(tmp_keyring) ; free(tmp_keyring) ; @@ -656,3 +676,56 @@ bool PGPHandler::isGPGAccepted(const std::string &id) return (res != _public_keyring_map.end()) && (res->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION) ; } +// Lexicographic order on signature packets +// +bool operator<(const ops_packet_t& p1,const ops_packet_t& p2) +{ + if(p1.length < p2.length) + return true ; + if(p1.length > p2.length) + return false ; + + for(int i=0;i p2.raw[i]) + return false ; + } + return false ; +} + +bool PGPHandler::mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) +{ + // First sort all signatures into lists to see which is new, which is not new + + std::cerr << "Merging signatures for key " << PGPIdType(dst->key_id).toStdString() << std::endl; + std::set dst_packets ; + + for(int i=0;inpackets;++i) dst_packets.insert(dst->packets[i]) ; + + std::set to_add ; + + for(int i=0;inpackets;++i) + if(dst_packets.find(src->packets[i]) == dst_packets.end()) + { + uint8_t tag ; + uint32_t length ; + + PGPKeyParser::read_packetHeader(src->packets[i].raw,tag,length) ; + + if(tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) + to_add.insert(src->packets[i]) ; + else + std::cerr << " Packet with tag 0x" << std::hex << (int)(src->packets[i].raw[0]) << std::dec << " not merged, because it is not a signature." << std::endl; + } + + for(std::set::const_iterator it(to_add.begin());it!=to_add.end();++it) + { + std::cerr << " Adding packet with tag 0x" << std::hex << (int)(*it).raw[0] << std::dec << std::endl; + ops_add_packet_to_keydata(dst,&*it) ; + } + return to_add.size() > 0 ; +} + + diff --git a/libretroshare/src/pgp/pgphandler.h b/libretroshare/src/pgp/pgphandler.h index d3637423e..5dd4e8f4a 100644 --- a/libretroshare/src/pgp/pgphandler.h +++ b/libretroshare/src/pgp/pgphandler.h @@ -130,5 +130,6 @@ class PGPHandler static ops_keyring_t *allocateOPSKeyring() ; static void addNewKeyToOPSKeyring(ops_keyring_t*, const ops_keydata_t&) ; static PassphraseCallback _passphrase_callback ; + static bool mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) ; // returns true if signature lists are different }; diff --git a/libretroshare/src/util/pgpkey.cc b/libretroshare/src/util/pgpkey.cc index 411bd2d15..27e81d93a 100644 --- a/libretroshare/src/util/pgpkey.cc +++ b/libretroshare/src/util/pgpkey.cc @@ -9,10 +9,6 @@ /* #define DEBUG_PGPUTIL 1 */ /****************************/ -#define PGP_PACKET_TAG_PUBLIC_KEY 6 -#define PGP_PACKET_TAG_USER_ID 13 -#define PGP_PACKET_TAG_SIGNATURE 2 - #define PGP_CRC24_INIT 0xB704CEL #define PGP_CRC24_POLY 0x1864CFBL @@ -85,11 +81,11 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std:: data += packet_length ; - if(packet_tag == PGP_PACKET_TAG_PUBLIC_KEY) + if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY) public_key = true ; - if(packet_tag == PGP_PACKET_TAG_USER_ID) + if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID) user_id = true ; - if(packet_tag == PGP_PACKET_TAG_SIGNATURE) + if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) own_signature = true ; if(public_key && own_signature && user_id) diff --git a/libretroshare/src/util/pgpkey.h b/libretroshare/src/util/pgpkey.h index a06954a24..1fd7ed9ab 100644 --- a/libretroshare/src/util/pgpkey.h +++ b/libretroshare/src/util/pgpkey.h @@ -71,6 +71,10 @@ class PGPKeyManagement class PGPKeyParser { public: + static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY = 6 ; + static const uint8_t PGP_PACKET_TAG_USER_ID = 13 ; + static const uint8_t PGP_PACKET_TAG_SIGNATURE = 2 ; + static uint64_t read_KeyID(unsigned char *& data) ; static uint32_t read_125Size(unsigned char *& data) ; static uint32_t read_partialBodyLength(unsigned char *& data) ; diff --git a/openpgpsdk/src/keyring.c b/openpgpsdk/src/keyring.c index f3419bf7b..e326193f7 100644 --- a/openpgpsdk/src/keyring.c +++ b/openpgpsdk/src/keyring.c @@ -184,14 +184,7 @@ void ops_keydata_copy(ops_keydata_t *dst,const ops_keydata_t *src) ops_copy_packet(dst->sigs[n].packet,src->sigs[n].packet) ; } - dst->key_id[0] = src->key_id[0] ; - dst->key_id[1] = src->key_id[1] ; - dst->key_id[2] = src->key_id[2] ; - dst->key_id[3] = src->key_id[3] ; - dst->key_id[4] = src->key_id[4] ; - dst->key_id[5] = src->key_id[5] ; - dst->key_id[6] = src->key_id[6] ; - dst->key_id[7] = src->key_id[7] ; + dst->key_id = src->key_id ; dst->type = src->type ; dst->key = src->key ; dst->fingerprint = src->fingerprint ;