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
This commit is contained in:
csoler 2012-06-15 21:58:46 +00:00
parent f50edd228f
commit 1b58ef74f8
5 changed files with 85 additions and 18 deletions

View File

@ -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<std::string,PGPCertificateInfo>::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<ops_keydata_t*>(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<p1.length;++i)
{
if(p1.raw[i] < p2.raw[i])
return true ;
if(p1.raw[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<ops_packet_t> dst_packets ;
for(int i=0;i<dst->npackets;++i) dst_packets.insert(dst->packets[i]) ;
std::set<ops_packet_t> to_add ;
for(int i=0;i<src->npackets;++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<ops_packet_t>::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 ;
}

View File

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

View File

@ -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)

View File

@ -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) ;

View File

@ -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 ;