Botan  1.11.15
src/lib/misc/openpgp/openpgp.cpp
Go to the documentation of this file.
00001 /*
00002 * OpenPGP Codec
00003 * (C) 1999-2007 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/openpgp.h>
00009 #include <botan/filters.h>
00010 #include <botan/basefilt.h>
00011 #include <botan/charset.h>
00012 #include <botan/crc24.h>
00013 
00014 namespace Botan {
00015 
00016 /*
00017 * OpenPGP Base64 encoding
00018 */
00019 std::string PGP_encode(
00020    const byte input[], size_t length,
00021    const std::string& label,
00022    const std::map<std::string, std::string>& headers)
00023    {
00024    const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n";
00025    const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n";
00026    const size_t PGP_WIDTH = 64;
00027 
00028    std::string pgp_encoded = PGP_HEADER;
00029 
00030    if(headers.find("Version") != headers.end())
00031       pgp_encoded += "Version: " + headers.find("Version")->second + '\n';
00032 
00033    std::map<std::string, std::string>::const_iterator i = headers.begin();
00034    while(i != headers.end())
00035       {
00036       if(i->first != "Version")
00037          pgp_encoded += i->first + ": " + i->second + '\n';
00038       ++i;
00039       }
00040    pgp_encoded += '\n';
00041 
00042    Pipe pipe(new Fork(
00043                 new Base64_Encoder(true, PGP_WIDTH),
00044                 new Chain(new Hash_Filter(new CRC24), new Base64_Encoder)
00045                 )
00046       );
00047 
00048    pipe.process_msg(input, length);
00049 
00050    pgp_encoded += pipe.read_all_as_string(0);
00051    pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n';
00052    pgp_encoded += PGP_TRAILER;
00053 
00054    return pgp_encoded;
00055    }
00056 
00057 /*
00058 * OpenPGP Base64 encoding
00059 */
00060 std::string PGP_encode(const byte input[], size_t length,
00061                        const std::string& type)
00062    {
00063    std::map<std::string, std::string> empty;
00064    return PGP_encode(input, length, type, empty);
00065    }
00066 
00067 /*
00068 * OpenPGP Base64 decoding
00069 */
00070 secure_vector<byte> PGP_decode(DataSource& source,
00071                               std::string& label,
00072                               std::map<std::string, std::string>& headers)
00073    {
00074    const size_t RANDOM_CHAR_LIMIT = 5;
00075 
00076    const std::string PGP_HEADER1 = "-----BEGIN PGP ";
00077    const std::string PGP_HEADER2 = "-----";
00078    size_t position = 0;
00079 
00080    while(position != PGP_HEADER1.length())
00081       {
00082       byte b;
00083       if(!source.read_byte(b))
00084          throw Decoding_Error("PGP: No PGP header found");
00085       if(b == PGP_HEADER1[position])
00086          ++position;
00087       else if(position >= RANDOM_CHAR_LIMIT)
00088          throw Decoding_Error("PGP: Malformed PGP header");
00089       else
00090          position = 0;
00091       }
00092    position = 0;
00093    while(position != PGP_HEADER2.length())
00094       {
00095       byte b;
00096       if(!source.read_byte(b))
00097          throw Decoding_Error("PGP: No PGP header found");
00098       if(b == PGP_HEADER2[position])
00099          ++position;
00100       else if(position)
00101          throw Decoding_Error("PGP: Malformed PGP header");
00102 
00103       if(position == 0)
00104          label += static_cast<char>(b);
00105       }
00106 
00107    headers.clear();
00108    bool end_of_headers = false;
00109    while(!end_of_headers)
00110       {
00111       std::string this_header;
00112       byte b = 0;
00113       while(b != '\n')
00114          {
00115          if(!source.read_byte(b))
00116             throw Decoding_Error("PGP: Bad armor header");
00117          if(b != '\n')
00118             this_header += static_cast<char>(b);
00119          }
00120 
00121       end_of_headers = true;
00122       for(size_t j = 0; j != this_header.length(); ++j)
00123          if(!Charset::is_space(this_header[j]))
00124             end_of_headers = false;
00125 
00126       if(!end_of_headers)
00127          {
00128          std::string::size_type pos = this_header.find(": ");
00129          if(pos == std::string::npos)
00130             throw Decoding_Error("OpenPGP: Bad headers");
00131 
00132          std::string key = this_header.substr(0, pos);
00133          std::string value = this_header.substr(pos + 2, std::string::npos);
00134          headers[key] = value;
00135          }
00136       }
00137 
00138    Pipe base64(new Base64_Decoder,
00139                new Fork(nullptr,
00140                         new Chain(new Hash_Filter(new CRC24),
00141                                   new Base64_Encoder)
00142                   )
00143       );
00144    base64.start_msg();
00145 
00146    const std::string PGP_TRAILER = "-----END PGP " + label + "-----";
00147    position = 0;
00148    bool newline_seen = 0;
00149    std::string crc;
00150    while(position != PGP_TRAILER.length())
00151       {
00152       byte b;
00153       if(!source.read_byte(b))
00154          throw Decoding_Error("PGP: No PGP trailer found");
00155       if(b == PGP_TRAILER[position])
00156          ++position;
00157       else if(position)
00158          throw Decoding_Error("PGP: Malformed PGP trailer");
00159 
00160       if(b == '=' && newline_seen)
00161          {
00162          while(b != '\n')
00163             {
00164             if(!source.read_byte(b))
00165                throw Decoding_Error("PGP: Bad CRC tail");
00166             if(b != '\n')
00167                crc += static_cast<char>(b);
00168             }
00169          }
00170       else if(b == '\n')
00171          newline_seen = true;
00172       else if(position == 0)
00173          {
00174          base64.write(b);
00175          newline_seen = false;
00176          }
00177       }
00178    base64.end_msg();
00179 
00180    if(crc != "" && crc != base64.read_all_as_string(1))
00181       throw Decoding_Error("PGP: Corrupt CRC");
00182 
00183    return base64.read_all();
00184    }
00185 
00186 /*
00187 * OpenPGP Base64 decoding
00188 */
00189 secure_vector<byte> PGP_decode(DataSource& source, std::string& label)
00190    {
00191    std::map<std::string, std::string> ignored;
00192    return PGP_decode(source, label, ignored);
00193    }
00194 
00195 }
00196