Botan  1.11.11
openpgp.cpp
Go to the documentation of this file.
1 /*
2 * OpenPGP Codec
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/openpgp.h>
9 #include <botan/filters.h>
10 #include <botan/basefilt.h>
11 #include <botan/charset.h>
12 #include <botan/crc24.h>
13 
14 namespace Botan {
15 
16 /*
17 * OpenPGP Base64 encoding
18 */
19 std::string PGP_encode(
20  const byte input[], size_t length,
21  const std::string& label,
22  const std::map<std::string, std::string>& headers)
23  {
24  const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n";
25  const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n";
26  const size_t PGP_WIDTH = 64;
27 
28  std::string pgp_encoded = PGP_HEADER;
29 
30  if(headers.find("Version") != headers.end())
31  pgp_encoded += "Version: " + headers.find("Version")->second + '\n';
32 
33  std::map<std::string, std::string>::const_iterator i = headers.begin();
34  while(i != headers.end())
35  {
36  if(i->first != "Version")
37  pgp_encoded += i->first + ": " + i->second + '\n';
38  ++i;
39  }
40  pgp_encoded += '\n';
41 
42  Pipe pipe(new Fork(
43  new Base64_Encoder(true, PGP_WIDTH),
44  new Chain(new Hash_Filter(new CRC24), new Base64_Encoder)
45  )
46  );
47 
48  pipe.process_msg(input, length);
49 
50  pgp_encoded += pipe.read_all_as_string(0);
51  pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n';
52  pgp_encoded += PGP_TRAILER;
53 
54  return pgp_encoded;
55  }
56 
57 /*
58 * OpenPGP Base64 encoding
59 */
60 std::string PGP_encode(const byte input[], size_t length,
61  const std::string& type)
62  {
63  std::map<std::string, std::string> empty;
64  return PGP_encode(input, length, type, empty);
65  }
66 
67 /*
68 * OpenPGP Base64 decoding
69 */
71  std::string& label,
72  std::map<std::string, std::string>& headers)
73  {
74  const size_t RANDOM_CHAR_LIMIT = 5;
75 
76  const std::string PGP_HEADER1 = "-----BEGIN PGP ";
77  const std::string PGP_HEADER2 = "-----";
78  size_t position = 0;
79 
80  while(position != PGP_HEADER1.length())
81  {
82  byte b;
83  if(!source.read_byte(b))
84  throw Decoding_Error("PGP: No PGP header found");
85  if(b == PGP_HEADER1[position])
86  ++position;
87  else if(position >= RANDOM_CHAR_LIMIT)
88  throw Decoding_Error("PGP: Malformed PGP header");
89  else
90  position = 0;
91  }
92  position = 0;
93  while(position != PGP_HEADER2.length())
94  {
95  byte b;
96  if(!source.read_byte(b))
97  throw Decoding_Error("PGP: No PGP header found");
98  if(b == PGP_HEADER2[position])
99  ++position;
100  else if(position)
101  throw Decoding_Error("PGP: Malformed PGP header");
102 
103  if(position == 0)
104  label += static_cast<char>(b);
105  }
106 
107  headers.clear();
108  bool end_of_headers = false;
109  while(!end_of_headers)
110  {
111  std::string this_header;
112  byte b = 0;
113  while(b != '\n')
114  {
115  if(!source.read_byte(b))
116  throw Decoding_Error("PGP: Bad armor header");
117  if(b != '\n')
118  this_header += static_cast<char>(b);
119  }
120 
121  end_of_headers = true;
122  for(size_t j = 0; j != this_header.length(); ++j)
123  if(!Charset::is_space(this_header[j]))
124  end_of_headers = false;
125 
126  if(!end_of_headers)
127  {
128  std::string::size_type pos = this_header.find(": ");
129  if(pos == std::string::npos)
130  throw Decoding_Error("OpenPGP: Bad headers");
131 
132  std::string key = this_header.substr(0, pos);
133  std::string value = this_header.substr(pos + 2, std::string::npos);
134  headers[key] = value;
135  }
136  }
137 
138  Pipe base64(new Base64_Decoder,
139  new Fork(nullptr,
140  new Chain(new Hash_Filter(new CRC24),
141  new Base64_Encoder)
142  )
143  );
144  base64.start_msg();
145 
146  const std::string PGP_TRAILER = "-----END PGP " + label + "-----";
147  position = 0;
148  bool newline_seen = 0;
149  std::string crc;
150  while(position != PGP_TRAILER.length())
151  {
152  byte b;
153  if(!source.read_byte(b))
154  throw Decoding_Error("PGP: No PGP trailer found");
155  if(b == PGP_TRAILER[position])
156  ++position;
157  else if(position)
158  throw Decoding_Error("PGP: Malformed PGP trailer");
159 
160  if(b == '=' && newline_seen)
161  {
162  while(b != '\n')
163  {
164  if(!source.read_byte(b))
165  throw Decoding_Error("PGP: Bad CRC tail");
166  if(b != '\n')
167  crc += static_cast<char>(b);
168  }
169  }
170  else if(b == '\n')
171  newline_seen = true;
172  else if(position == 0)
173  {
174  base64.write(b);
175  newline_seen = false;
176  }
177  }
178  base64.end_msg();
179 
180  if(crc != "" && crc != base64.read_all_as_string(1))
181  throw Decoding_Error("PGP: Corrupt CRC");
182 
183  return base64.read_all();
184  }
185 
186 /*
187 * OpenPGP Base64 decoding
188 */
189 secure_vector<byte> PGP_decode(DataSource& source, std::string& label)
190  {
191  std::map<std::string, std::string> ignored;
192  return PGP_decode(source, label, ignored);
193  }
194 
195 }
196 
void start_msg()
Definition: pipe.cpp:158
std::string PGP_encode(const byte input[], size_t length, const std::string &label, const std::map< std::string, std::string > &headers)
Definition: openpgp.cpp:19
std::string read_all_as_string(message_id=DEFAULT_MESSAGE)
Definition: pipe_rw.cpp:110
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:35
void end_msg()
Definition: pipe.cpp:172
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:92
uint8_t byte
Definition: types.h:30
size_t read_byte(byte &out)
Definition: data_src.cpp:19
Definition: buf_comp.h:15
secure_vector< byte > read_all(message_id msg=DEFAULT_MESSAGE)
Definition: pipe_rw.cpp:98
secure_vector< byte > PGP_decode(DataSource &source, std::string &label, std::map< std::string, std::string > &headers)
Definition: openpgp.cpp:70
bool is_space(char c)
Definition: charset.cpp:139
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:117