Botan: src/codec/openpgp/openpgp.cpp Source File

Botan 1.10.17

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 */
70 SecureVector<byte> PGP_decode(DataSource& source,
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(0,
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 SecureVector<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
Botan::Pipe::start_msg
void start_msg()
Definition: pipe.cpp:152
Botan::PGP_decode
SecureVector< byte > PGP_decode(DataSource &source, std::string &label, std::map< std::string, std::string > &headers)
Definition: openpgp.cpp:70
Botan::Chain
Definition: basefilt.h:31
Botan::PGP_encode
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
Botan::Pipe::read_all_as_string
std::string read_all_as_string(message_id=DEFAULT_MESSAGE)
Definition: pipe_rw.cpp:117
Botan::Pipe::write
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
Botan::Hash_Filter
Definition: filters.h:104
Botan::DataSource
Definition: data_src.h:20
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::Pipe::end_msg
void end_msg()
Definition: pipe.cpp:166
Botan::Pipe::read_all
SecureVector< byte > read_all(message_id msg=DEFAULT_MESSAGE)
Definition: pipe_rw.cpp:105
Botan::CRC24
Definition: crc24.h:18
Botan::Base64_Decoder
Definition: b64_filt.h:57
Botan::Decoding_Error
Definition: exceptn.h:138
Botan::DataSource::read_byte
size_t read_byte(byte &out)
Definition: data_src.cpp:19
Botan::Base64_Encoder
Definition: b64_filt.h:18
Botan
Definition: algo_base.h:14
Botan::Charset::is_space
bool is_space(char c)
Definition: charset.cpp:139
Botan::Fork
Definition: basefilt.h:57
Botan::SecureVector< byte >
Botan::Pipe
Definition: pipe.h:25
Botan::Pipe::process_msg
void process_msg(const byte in[], size_t length)
Definition: pipe.cpp:116