[tor-commits] [stegotorus/master] Tidy up the base64 encoder/decoder a bit.

zwol at torproject.org zwol at torproject.org
Fri Jul 20 23:17:07 UTC 2012


commit 04822445ed3b56ab2b4cb0ca3bc8fec678b65fa5
Author: Zack Weinberg <zackw at 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>





More information about the tor-commits mailing list