diff options
author | lloyd <[email protected]> | 2008-09-28 22:14:54 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-28 22:14:54 +0000 |
commit | 31204986023619c385d378e79a6511bb81ef7b78 (patch) | |
tree | ce272a6585dc070f750f6875b0450d53145b935d /src/codec/base64/base64.cpp | |
parent | 42c0fe76ab6d9625d0e51c68b8dd187322c991bd (diff) |
Move almost all of the ASN.1, BER, and DER codec related code into new
module asn1
Move hex and base64 codecs into new codecs directory. Also move zlib and
bzip2 to codecs from compress.
Diffstat (limited to 'src/codec/base64/base64.cpp')
-rw-r--r-- | src/codec/base64/base64.cpp | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/src/codec/base64/base64.cpp b/src/codec/base64/base64.cpp new file mode 100644 index 000000000..0e01d94f3 --- /dev/null +++ b/src/codec/base64/base64.cpp @@ -0,0 +1,225 @@ +/************************************************* +* Base64 Encoder/Decoder Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/base64.h> +#include <botan/charset.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* Base64_Encoder Constructor * +*************************************************/ +Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) : + line_length(breaks ? length : 0), trailing_newline(t_n) + { + in.create(48); + out.create(4); + + counter = position = 0; + } + +/************************************************* +* Base64 Encoding Operation * +*************************************************/ +void Base64_Encoder::encode(const byte in[3], byte out[4]) + { + out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)]; + out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)]; + out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )]; + } + +/************************************************* +* Encode and send a block * +*************************************************/ +void Base64_Encoder::encode_and_send(const byte block[], u32bit length) + { + for(u32bit j = 0; j != length; j += 3) + { + encode(block + j, out); + do_output(out, 4); + } + } + +/************************************************* +* Handle the output * +*************************************************/ +void Base64_Encoder::do_output(const byte input[], u32bit length) + { + if(line_length == 0) + send(input, length); + else + { + u32bit remaining = length, offset = 0; + while(remaining) + { + u32bit sent = std::min(line_length - counter, remaining); + send(input + offset, sent); + counter += sent; + remaining -= sent; + offset += sent; + if(counter == line_length) + { + send('\n'); + counter = 0; + } + } + } + } + +/************************************************* +* Convert some data into Base64 * +*************************************************/ +void Base64_Encoder::write(const byte input[], u32bit length) + { + in.copy(position, input, length); + if(position + length >= in.size()) + { + encode_and_send(in, in.size()); + input += (in.size() - position); + length -= (in.size() - position); + while(length >= in.size()) + { + encode_and_send(input, in.size()); + input += in.size(); + length -= in.size(); + } + in.copy(input, length); + position = 0; + } + position += length; + } + +/************************************************* +* Flush buffers * +*************************************************/ +void Base64_Encoder::end_msg() + { + u32bit start_of_last_block = 3 * (position / 3), + left_over = position % 3; + encode_and_send(in, start_of_last_block); + + if(left_over) + { + SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over); + + encode(remainder, out); + + u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1; + while(empty_bits >= 8) + { + out[index--] = '='; + empty_bits -= 6; + } + + do_output(out, 4); + } + + if(trailing_newline || (counter && line_length)) + send('\n'); + + counter = position = 0; + } + +/************************************************* +* Base64_Decoder Constructor * +*************************************************/ +Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c) + { + in.create(48); + out.create(3); + position = 0; + } + +/************************************************* +* Check if a character is a valid Base64 char * +*************************************************/ +bool Base64_Decoder::is_valid(byte in) + { + return (BASE64_TO_BIN[in] != 0x80); + } + +/************************************************* +* Base64 Decoding Operation * +*************************************************/ +void Base64_Decoder::decode(const byte in[4], byte out[3]) + { + out[0] = ((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4)); + out[1] = ((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2)); + out[2] = ((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]])); + } + +/************************************************* +* Decode and send a block * +*************************************************/ +void Base64_Decoder::decode_and_send(const byte block[], u32bit length) + { + for(u32bit j = 0; j != length; j += 4) + { + decode(block + j, out); + send(out, 3); + } + } + +/************************************************* +* Handle processing an invalid character * +*************************************************/ +void Base64_Decoder::handle_bad_char(byte c) + { + if(c == '=' || checking == NONE) + return; + + if((checking == IGNORE_WS) && Charset::is_space(c)) + return; + + throw Decoding_Error( + std::string("Base64_Decoder: Invalid base64 character '") + + static_cast<char>(c) + "'" + ); + } + +/************************************************* +* Convert some data from Base64 * +*************************************************/ +void Base64_Decoder::write(const byte input[], u32bit length) + { + for(u32bit j = 0; j != length; ++j) + { + if(is_valid(input[j])) + in[position++] = input[j]; + else + handle_bad_char(input[j]); + + if(position == in.size()) + { + decode_and_send(in, in.size()); + position = 0; + } + } + } + +/************************************************* +* Flush buffers * +*************************************************/ +void Base64_Decoder::end_msg() + { + if(position != 0) + { + u32bit start_of_last_block = 4 * (position / 4), + left_over = position % 4; + decode_and_send(in, start_of_last_block); + + if(left_over) + { + SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over); + decode(remainder, out); + send(out, ((left_over == 1) ? (1) : (left_over - 1))); + } + } + position = 0; + } + +} |