commit 04822445ed3b56ab2b4cb0ca3bc8fec678b65fa5 Author: Zack Weinberg zackw@panix.com Date: Thu Mar 1 08:10:52 2012 -0800
Tidy up the base64 encoder/decoder a bit. --- Makefile.am | 3 +- src/base64.cc | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ src/base64.h | 46 ++++++++++++ src/steg/b64decode.cc | 88 ---------------------- src/steg/b64decode.h | 54 -------------- src/steg/b64encode.cc | 139 ----------------------------------- src/steg/b64encode.h | 62 ---------------- src/steg/http.cc | 2 +- 8 files changed, 241 insertions(+), 346 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 280f32a..978c180 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,8 +20,6 @@ PROTOCOLS = \
STEGANOGRAPHERS = \ src/steg/b64cookies.cc \ - src/steg/b64encode.cc \ - src/steg/b64decode.cc \ src/steg/cookies.cc \ src/steg/crc32.cc \ src/steg/embed.cc \ @@ -35,6 +33,7 @@ STEGANOGRAPHERS = \ src/steg/zpack.cc
libstegotorus_a_SOURCES = \ + src/base64.cc \ src/connections.cc \ src/crypt.cc \ src/network.cc \ diff --git a/src/base64.cc b/src/base64.cc new file mode 100644 index 0000000..8d53d0f --- /dev/null +++ b/src/base64.cc @@ -0,0 +1,193 @@ +/* Base-64 encoding and decoding. Based on the libb64 project + (http://sourceforge.net/projects/libb64) whose code is placed in the + public domain. */ + +#include "base64.h" +#include <stdlib.h> + +const int CHARS_PER_LINE = 72; + +static char +encode1(char v) +{ + const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned int value_in = v; + if (value_in > sizeof(encoding)-1) return '='; + return encoding[value_in]; +} + +/* assumes ASCII */ +static int +decode1(char v) +{ + const signed char decoding[] = { + // + , - . / 0 1 2 3 4 5 6 7 8 9 + 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + // : ; < = > ? @ + -1, -1, -1, -1, -1, -1, -1, + // A B C D E F G H I J K L M + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + // N O P Q R S T U V W X Y Z + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + // [ \ ] ^ _ ` + -1, -1, -1, -1, -1, -1, + // a b c d e f g h i j k l m + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + // n o p q r s t u v w x y z + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + unsigned int value_in = v; + value_in -= 43; + if (value_in > sizeof(decoding)) + return -1; + return decoding[value_in]; +} + +namespace base64 +{ + +ptrdiff_t +encoder::encode(const char* plaintext_in, size_t length_in, char* code_out) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = this->result; + + switch (this->step) { + for (;;) { + case step_A: + if (plainchar == plaintextend) { + this->result = result; + this->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = encode1(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) { + this->result = result; + this->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = encode1(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) { + this->result = result; + this->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = encode1(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = encode1(result); + + ++(this->stepcount); + if (this->stepcount == CHARS_PER_LINE/4) { + *codechar++ = '\n'; + this->stepcount = 0; + } + } + default: + abort(); + } +} + +ptrdiff_t +encoder::encode_end(char* code_out) +{ + char* codechar = code_out; + + switch (this->step) { + case step_B: + *codechar++ = encode1(this->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = encode1(this->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar++ = '\n'; + + /* reset */ + this->step = step_A; + this->stepcount = 0; + this->result = 0; + return codechar - code_out; +} + +ptrdiff_t +decoder::decode(const char* code_in, size_t length_in, char* plaintext_out) +{ + const char* codechar = code_in; + char* plainchar = plaintext_out; + int fragment; + + *plainchar = this->plainchar; + + switch (this->step) { + while (1) { + case step_A: + do { + if (codechar == code_in+length_in) { + this->step = step_A; + this->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = decode1(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + case step_B: + do { + if (codechar == code_in+length_in) { + this->step = step_B; + this->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = decode1(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + case step_C: + do { + if (codechar == code_in+length_in) { + this->step = step_C; + this->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = decode1(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + case step_D: + do { + if (codechar == code_in+length_in) { + this->step = step_D; + this->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = decode1(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + default: + abort(); + } +} + +} // namespace base64 diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 0000000..adc0dae --- /dev/null +++ b/src/base64.h @@ -0,0 +1,46 @@ +/* Base-64 encoding and decoding. Based on the libb64 project + (http://sourceforge.net/projects/libb64) whose code is placed in the + public domain. */ + +#ifndef ST_BASE64_H +#define ST_BASE64_H + +#include <stddef.h> + +namespace base64 +{ + +class encoder +{ + enum encode_step { step_A, step_B, step_C }; + encode_step step; + int stepcount; + char result; + +public: + encoder() + : step(step_A), stepcount(0), result(0) + {} + + ptrdiff_t encode(const char* plaintext_in, size_t length_in, char* code_out); + ptrdiff_t encode_end(char* code_out); +}; + +class decoder +{ + enum decode_step { step_A, step_B, step_C, step_D }; + decode_step step; + char plainchar; + +public: + decoder() + : step(step_A), plainchar(0) + {} + + ptrdiff_t decode(const char* code_in, size_t length_in, char* plaintext_out); + void reset() { step = step_A; plainchar = 0; } +}; + +} // namespace base64 + +#endif // ST_BASE64_H diff --git a/src/steg/b64decode.cc b/src/steg/b64decode.cc deleted file mode 100755 index 3beffba..0000000 --- a/src/steg/b64decode.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* -cdecoder.c - c source to a base64 decoding algorithm implementation - -This is part of the libb64 project, and has been placed in the public domain. -For details, see http://sourceforge.net/projects/libb64 -*/ - -#include "b64decode.h" - -int base64_decode_value(char value_in) -{ - static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; - static const char decoding_size = sizeof(decoding); - value_in -= 43; - if (value_in < 0 || value_in > decoding_size) return -1; - return decoding[(int)value_in]; -} - -void base64_init_decodestate(base64_decodestate* state_in) -{ - state_in->step = step_a; - state_in->plainchar = 0; -} - -int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) -{ - const char* codechar = code_in; - char* plainchar = plaintext_out; - char fragment; - - *plainchar = state_in->plainchar; - - switch (state_in->step) - { - while (1) - { - case step_a: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_a; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar = (fragment & 0x03f) << 2; - case step_b: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_b; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar++ |= (fragment & 0x030) >> 4; - *plainchar = (fragment & 0x00f) << 4; - case step_c: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_c; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar++ |= (fragment & 0x03c) >> 2; - *plainchar = (fragment & 0x003) << 6; - case step_d: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_d; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar++ |= (fragment & 0x03f); - } - } - /* control should not reach here */ - return plainchar - plaintext_out; -} - diff --git a/src/steg/b64decode.h b/src/steg/b64decode.h deleted file mode 100755 index c2388b6..0000000 --- a/src/steg/b64decode.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -cdecode.h - c header for a base64 decoding algorithm - -This is part of the libb64 project, and has been placed in the public domain. -For details, see http://sourceforge.net/projects/libb64 -*/ - -#ifndef BASE64_CDECODE_H -#define BASE64_CDECODE_H - -#include "b64encode.h" - -enum base64_decodestep -{ - step_a, step_b, step_c, step_d -}; - -struct base64_decodestate -{ - base64_decodestep step; - char plainchar; -}; - -void base64_init_decodestate(base64_decodestate* state_in); -int base64_decode_value(char value_in); -int base64_decode_block(const char* code_in, const int length_in, - char* plaintext_out, base64_decodestate* state_in); - -namespace base64 -{ - struct decoder - { - base64_decodestate _state; - int _buffersize; - - decoder(int buffersize_in = BUFFERSIZE) - : _buffersize(buffersize_in) - { - } - - int decode(char value_in) - { - return base64_decode_value(value_in); - } - - int decode(const char* code_in, const int length_in, char* plaintext_out) - { - base64_init_decodestate(&_state); - return base64_decode_block(code_in, length_in, plaintext_out, &_state); - } - }; -} // namespace base64 - -#endif /* BASE64_CDECODE_H */ diff --git a/src/steg/b64encode.cc b/src/steg/b64encode.cc deleted file mode 100755 index 1f1352d..0000000 --- a/src/steg/b64encode.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* -cencoder.c - c source to a base64 encoding algorithm implementation - -This is part of the libb64 project, and has been placed in the public domain. -For details, see http://sourceforge.net/projects/libb64 -*/ - - -#include "b64encode.h" -#include "b64decode.h" - - -const int CHARS_PER_LINE = 72; - -void base64_init_encodestate(base64_encodestate* state_in) -{ - state_in->step = step_A; - state_in->result = 0; - state_in->stepcount = 0; -} - -char base64_encode_value(char value_in) -{ - static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - if (value_in > 63) return '='; - return encoding[(int)value_in]; -} - -int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) -{ - const char* plainchar = plaintext_in; - const char* const plaintextend = plaintext_in + length_in; - char* codechar = code_out; - char result; - char fragment; - - result = state_in->result; - - switch (state_in->step) - { - while (1) - { - case step_A: - if (plainchar == plaintextend) - { - state_in->result = result; - state_in->step = step_A; - return codechar - code_out; - } - fragment = *plainchar++; - result = (fragment & 0x0fc) >> 2; - *codechar++ = base64_encode_value(result); - result = (fragment & 0x003) << 4; - case step_B: - if (plainchar == plaintextend) - { - state_in->result = result; - state_in->step = step_B; - return codechar - code_out; - } - fragment = *plainchar++; - result |= (fragment & 0x0f0) >> 4; - *codechar++ = base64_encode_value(result); - result = (fragment & 0x00f) << 2; - case step_C: - if (plainchar == plaintextend) - { - state_in->result = result; - state_in->step = step_C; - return codechar - code_out; - } - fragment = *plainchar++; - result |= (fragment & 0x0c0) >> 6; - *codechar++ = base64_encode_value(result); - result = (fragment & 0x03f) >> 0; - *codechar++ = base64_encode_value(result); - - ++(state_in->stepcount); - if (state_in->stepcount == CHARS_PER_LINE/4) - { - *codechar++ = '\n'; - state_in->stepcount = 0; - } - } - } - - - - - /* control should not reach here */ - return codechar - code_out; -} - -int base64_encode_blockend(char* code_out, base64_encodestate* state_in) -{ - char* codechar = code_out; - - switch (state_in->step) - { - case step_B: - *codechar++ = base64_encode_value(state_in->result); - *codechar++ = '='; - *codechar++ = '='; - break; - case step_C: - *codechar++ = base64_encode_value(state_in->result); - *codechar++ = '='; - break; - case step_A: - break; - } - *codechar++ = '\n'; - - return codechar - code_out; -} - - - - -/* -int main() { - - char foo[12] = "AbcdwefA#"; - char foo2[22]; - - base64::encoder E; - - printf("%d\n", (int) strlen(foo)); - E.encode(foo, strlen(foo), foo2); - printf("%s\n", foo2); - printf("%d\n", E.encode_end(foo2+strlen(foo2))); - printf("%s\n", foo2); - - base64::decoder D; - D.decode(foo2, strlen(foo2), foo); - printf("%s\n", foo); -} - -*/ diff --git a/src/steg/b64encode.h b/src/steg/b64encode.h deleted file mode 100755 index 4831d74..0000000 --- a/src/steg/b64encode.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - cencode.h - c header for a base64 encoding algorithm - - This is part of the libb64 project, and has been placed in the public domain. - For details, see http://sourceforge.net/projects/libb64 -*/ - -#ifndef BASE64_CENCODE_H -#define BASE64_CENCODE_H - -enum base64_encodestep -{ - step_A, step_B, step_C -}; - -struct base64_encodestate -{ - base64_encodestep step; - char result; - int stepcount; -}; - -void base64_init_encodestate(base64_encodestate* state_in); -char base64_encode_value(char value_in); -int base64_encode_block(const char* plaintext_in, int length_in, - char* code_out, base64_encodestate* state_in); - -int base64_encode_blockend(char* code_out, base64_encodestate* state_in); - -static int BUFFERSIZE = 16777216; - -namespace base64 -{ - struct encoder - { - base64_encodestate _state; - int _buffersize; - - encoder(int buffersize_in = BUFFERSIZE) - : _buffersize(buffersize_in) - {} - - int encode(char value_in) - { - return base64_encode_value(value_in); - } - - int encode(const char* code_in, const int length_in, char* plaintext_out) - { - base64_init_encodestate(&_state); - return base64_encode_block(code_in, length_in, plaintext_out, &_state); - } - - int encode_end(char* plaintext_out) - { - return base64_encode_blockend(plaintext_out, &_state); - } - }; - -} // namespace base64 - -#endif /* BASE64_CENCODE_H */ diff --git a/src/steg/http.cc b/src/steg/http.cc index 06ef332..5a78ffe 100644 --- a/src/steg/http.cc +++ b/src/steg/http.cc @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "swfSteg.h" #include "pdfSteg.h" #include "jsSteg.h" -#include "b64decode.h" +#include "base64.h" #include "b64cookies.h"
#include <event2/buffer.h>
tor-commits@lists.torproject.org