Botan
1.11.15
|
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