00001
00002
00003
00004
00005
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
00018
00019 std::string PGP_encode(
00020 const byte input[], u32bit 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 u32bit 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
00059
00060 std::string PGP_encode(const byte input[], u32bit 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
00069
00070 SecureVector<byte> PGP_decode(DataSource& source,
00071 std::string& label,
00072 std::map<std::string, std::string>& headers)
00073 {
00074 const u32bit RANDOM_CHAR_LIMIT = 5;
00075
00076 const std::string PGP_HEADER1 = "-----BEGIN PGP ";
00077 const std::string PGP_HEADER2 = "-----";
00078 u32bit 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(u32bit 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(0,
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
00188
00189 SecureVector<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