mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-02 14:16:16 -04:00
- moved pgpkey.h/cc into pgp directory
- fixed bug in key cleaning code git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-OpenPGP@5291 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
f5c276c9b5
commit
ddf503a793
7 changed files with 18 additions and 7 deletions
|
@ -1,245 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <util/radix64.h>
|
||||
#include "pgpkey.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
/****************************/
|
||||
/* #define DEBUG_PGPUTIL 1 */
|
||||
/****************************/
|
||||
|
||||
#define PGP_CRC24_INIT 0xB704CEL
|
||||
#define PGP_CRC24_POLY 0x1864CFBL
|
||||
|
||||
#define PGP_CERTIFICATE_START_STRING "-----BEGIN PGP PUBLIC KEY BLOCK-----"
|
||||
#define PGP_CERTIFICATE_END_STRING "-----END PGP PUBLIC KEY BLOCK-----"
|
||||
//
|
||||
// All size are big endian
|
||||
// MPI: 2 bytes size (length in bits) + string of octets
|
||||
//
|
||||
bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 0 - Extract Radix64 portion of the certificate
|
||||
//
|
||||
int n = pgp_certificate.length() ;
|
||||
int i=0 ;
|
||||
std::string version_string = "" ;
|
||||
|
||||
while(i < n && pgp_certificate[i] != '\n') ++i ; // remove first part -----BEGIN PGP CERTIFICATE-----
|
||||
++i ;
|
||||
while(i < n && pgp_certificate[i] != '\n') version_string += pgp_certificate[i++] ; // remove first part Version: [fdfdfdf]
|
||||
++i ;
|
||||
while(i < n && pgp_certificate[i] != '\n') ++i ; // remove blank line
|
||||
|
||||
++i ;
|
||||
|
||||
int j=n-1 ;
|
||||
|
||||
while(j>0 && pgp_certificate[j] != '=' && j>=i) --j ;
|
||||
|
||||
std::string radix_cert = pgp_certificate.substr(i,j-i) ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "extracted radix cert: " << std::endl;
|
||||
std::cerr << radix_cert ;
|
||||
#endif
|
||||
|
||||
// 1 - Convert armored key into binary key
|
||||
//
|
||||
|
||||
char *keydata = NULL ;
|
||||
size_t len = 0 ;
|
||||
|
||||
Radix64::decode(radix_cert,keydata,len) ;
|
||||
|
||||
unsigned char *data = (unsigned char *)keydata ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Total size: " << len << std::endl;
|
||||
#endif
|
||||
|
||||
uint8_t packet_tag;
|
||||
uint32_t packet_length ;
|
||||
|
||||
// 2 - parse key data, only keep public key data, user id and self-signature.
|
||||
|
||||
bool public_key=false ;
|
||||
bool own_signature=false ;
|
||||
bool user_id=false ;
|
||||
|
||||
while(true)
|
||||
{
|
||||
PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ;
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Header:" << std::endl;
|
||||
std::cerr << " Packet tag: " << (int)packet_tag << std::endl;
|
||||
std::cerr << " Packet length: " << packet_length << std::endl;
|
||||
#endif
|
||||
|
||||
data += packet_length ;
|
||||
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY)
|
||||
public_key = true ;
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID)
|
||||
user_id = true ;
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE)
|
||||
own_signature = true ;
|
||||
|
||||
if(public_key && own_signature && user_id)
|
||||
break ;
|
||||
|
||||
if( (uint64_t)data - (uint64_t)keydata >= len )
|
||||
break ;
|
||||
}
|
||||
|
||||
cleaned_certificate = makeArmouredKey((unsigned char*)keydata,(uint64_t)data - (uint64_t)keydata,version_string) ;
|
||||
return true ;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
cleaned_certificate = "" ;
|
||||
std::cerr << "Certificate cleaning failed: " << e.what() << std::endl;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
std::string PGPKeyManagement::makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string)
|
||||
{
|
||||
std::string outstring ;
|
||||
Radix64::encode((const char *)keydata,key_size,outstring) ;
|
||||
|
||||
uint32_t crc = compute24bitsCRC((unsigned char *)keydata,key_size) ;
|
||||
|
||||
unsigned char tmp[3] = { (crc >> 16) & 0xff, (crc >> 8) & 0xff, crc & 0xff } ;
|
||||
std::string crc_string ;
|
||||
Radix64::encode((const char *)tmp,3,crc_string) ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "After signature pruning: " << std::endl;
|
||||
std::cerr << outstring << std::endl;
|
||||
#endif
|
||||
|
||||
std::string certificate = std::string(PGP_CERTIFICATE_START_STRING) + "\n" + version_string + "\n\n" ;
|
||||
|
||||
for(uint32_t i=0;i<outstring.length();i+=64)
|
||||
certificate += outstring.substr(i,64) + "\n" ;
|
||||
|
||||
certificate += "=" + crc_string + "\n" ;
|
||||
certificate += std::string(PGP_CERTIFICATE_END_STRING) + "\n" ;
|
||||
|
||||
return certificate ;
|
||||
}
|
||||
|
||||
uint32_t PGPKeyManagement::compute24bitsCRC(unsigned char *octets, size_t len)
|
||||
{
|
||||
long crc = PGP_CRC24_INIT;
|
||||
int i;
|
||||
while (len--) {
|
||||
crc ^= (*octets++) << 16;
|
||||
for (i = 0; i < 8; i++) {
|
||||
crc <<= 1;
|
||||
if (crc & 0x1000000)
|
||||
crc ^= PGP_CRC24_POLY;
|
||||
}
|
||||
}
|
||||
return crc & 0xFFFFFFL;
|
||||
}
|
||||
|
||||
uint64_t PGPKeyParser::read_KeyID(unsigned char *& data)
|
||||
{
|
||||
uint64_t val = 0 ;
|
||||
|
||||
val |= uint64_t( *data ) << 56 ; ++data ;
|
||||
val |= uint64_t( *data ) << 48 ; ++data ;
|
||||
val |= uint64_t( *data ) << 40 ; ++data ;
|
||||
val |= uint64_t( *data ) << 32 ; ++data ;
|
||||
val |= uint64_t( *data ) << 24 ; ++data ;
|
||||
val |= uint64_t( *data ) << 16 ; ++data ;
|
||||
val |= uint64_t( *data ) << 8 ; ++data ;
|
||||
val |= uint64_t( *data ) << 0 ; ++data ;
|
||||
|
||||
return val ;
|
||||
}
|
||||
|
||||
uint32_t PGPKeyParser::read_125Size(unsigned char *& data)
|
||||
{
|
||||
uint8_t b1 = *data ;
|
||||
++data ;
|
||||
|
||||
if(b1 < 192)
|
||||
return b1 ;
|
||||
|
||||
uint8_t b2 = *data ;
|
||||
++data ;
|
||||
|
||||
if(b1 < 224)
|
||||
return ((b1-192) << 8) + b2 + 192 ;
|
||||
|
||||
if(b1 != 0xff)
|
||||
throw std::runtime_error("GPG parsing error") ;
|
||||
|
||||
uint8_t b3 = *data ; ++data ;
|
||||
uint8_t b4 = *data ; ++data ;
|
||||
uint8_t b5 = *data ; ++data ;
|
||||
|
||||
return (b2 << 24) | (b3 << 16) | (b4 << 8) | b5 ;
|
||||
}
|
||||
|
||||
uint32_t PGPKeyParser::read_partialBodyLength(unsigned char *& data)
|
||||
{
|
||||
uint8_t b1 =*data ;
|
||||
++data ;
|
||||
|
||||
return 1 << (b1 & 0x1F) ;
|
||||
}
|
||||
|
||||
|
||||
void PGPKeyParser::read_packetHeader(unsigned char *& data,uint8_t& packet_tag,uint32_t& packet_length)
|
||||
{
|
||||
uint8_t b1 = *data ;
|
||||
++data ;
|
||||
|
||||
bool new_format = b1 & 0x40 ;
|
||||
|
||||
if(new_format)
|
||||
{
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Packet is in new format" << std::endl;
|
||||
#endif
|
||||
packet_tag = b1 & 0x3f ;
|
||||
packet_length = read_125Size(data) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Packet is in old format" << std::endl;
|
||||
#endif
|
||||
uint8_t length_type = b1 & 0x03 ;
|
||||
packet_tag = (b1 & 0x3c) >> 2 ;
|
||||
|
||||
int length_size ;
|
||||
switch(length_type)
|
||||
{
|
||||
case 0: length_size = 1 ;
|
||||
break ;
|
||||
case 1: length_size = 2 ;
|
||||
break ;
|
||||
case 2: length_size = 4 ;
|
||||
break ;
|
||||
default:
|
||||
throw std::runtime_error("Unhandled length type!") ;
|
||||
}
|
||||
|
||||
packet_length = 0 ;
|
||||
for(int k=0;k<length_size;++k)
|
||||
{
|
||||
packet_length <<= 8 ;
|
||||
packet_length |= *data ;
|
||||
++data ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/****************************************************************
|
||||
* RetroShare is distributed under the following license:
|
||||
*
|
||||
* Copyright (C) 2012 Cyril Soler <csoler@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
****************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
// refer to RFC4880 specif document for loading GPG public keys:
|
||||
//
|
||||
// 11.1: transferable public keys
|
||||
// Global structure of transferable public keys
|
||||
//
|
||||
// - one public key packet (see 12.2)
|
||||
// - zero or more revocation signatures (See signature type 5.2.1 for key signature types)
|
||||
//
|
||||
// - user certification signatures (0x10 or 0x13)
|
||||
//
|
||||
// - 5.2.2: Signature format packet
|
||||
// - 5.2.3.1: signature subpacket specification
|
||||
//
|
||||
// - 4.3: packet tags (1 byte)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
// This class handles GPG keys. For now we only clean them from signatures, but
|
||||
// in the future, we might cache them to avoid unnecessary calls to gpgme.
|
||||
//
|
||||
class PGPKeyManagement
|
||||
{
|
||||
public:
|
||||
// Create a minimal key, removing all signatures and third party info.
|
||||
// Input: a clean PGP certificate (starts with "----BEGIN",
|
||||
// ends with "-----END PGP PUBLIC KEY BLOCK-----"
|
||||
// Output: the same certificate without signatures.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// true if the certificate cleaning succeeded
|
||||
// false otherwise.
|
||||
//
|
||||
static bool createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) ;
|
||||
|
||||
static std::string makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) ;
|
||||
private:
|
||||
// Computes the 24 bits CRC checksum necessary to all PGP data.
|
||||
//
|
||||
static uint32_t compute24bitsCRC(unsigned char *data,size_t len) ;
|
||||
};
|
||||
|
||||
// This class handles the parsing of PGP packet headers under various (old and new) formats.
|
||||
//
|
||||
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) ;
|
||||
static void read_packetHeader(unsigned char *& data,uint8_t& packet_tag,uint32_t& packet_length) ;
|
||||
};
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue