BASE64的实现

原由

项目中经常需要使用base64进行处理,通过base64可以将特殊字符转化为普通可见字符,便于网络传输,代价是增长了传输长度。

base64将每3个byte转化为4个6bit位,然后高位补两个零。这意味着,base64编码后长度会变长。

  1. 当源文长度不是3的倍数时,需要补零。编码后以等号“=”表示。至多有1至2个补零的情况出现,则结尾最多一至两个等号。
  2. 编码后长度可预测4*(len+2)/3。
  3. base64是个可逆编码。
  4. 源文长度预估如下:末尾等号个数为p(此时p小于等于2),编码长度l (此时l为4的倍数),则源文长度 ( l * 3/4 - p)
源文 源长度 base编码后 编码后长度
abc 3 YWJj 4
abca 4 YWJjYQ== 8
abcab 5 YWJjYWI= 8
abcabc 6 YWJjYWJj 8

 

 

 

源码请见:https://github.com/fpzeng/aes128

C语言实现

base64的源码其实没有几行,但是在项目代码中添加base64源码总有造轮子的嫌疑。这里使用libopenssl库。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <openssl/bio.h>
 4 #include <openssl/evp.h>
 5 #include <stdio.h>
 6 #include <math.h>
 7  
 8 int Base64Encode(const char* message, char** buffer) { //Encodes a string to base64
 9   BIO *bio, *b64;
10   FILE* stream;
11   int encodedSize = 4*ceil((double)strlen(message)/3);
12   *buffer = (char *)malloc(encodedSize+1);
13  
14   stream = fmemopen(*buffer, encodedSize+1, "w");
15   b64 = BIO_new(BIO_f_base64());
16   bio = BIO_new_fp(stream, BIO_NOCLOSE);
17   bio = BIO_push(b64, bio);
18   BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line
19   BIO_write(bio, message, strlen(message));
20   BIO_flush(bio);
21   BIO_free_all(bio);
22   fclose(stream);
23  
24   return (0); //success
25 }
26 int calcDecodeLength(const char* b64input) { //Calculates the length of a decoded base64 string
27   int len = strlen(b64input);
28   int padding = 0;
29  
30   if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
31     padding = 2;
32   else if (b64input[len-1] == '=') //last char is =
33     padding = 1;
34  
35   return (int)len*0.75 - padding;
36 }
37  
38 int Base64Decode(char* b64message, char** buffer) { //Decodes a base64 encoded string
39   BIO *bio, *b64;
40   int decodeLen = calcDecodeLength(b64message),
41       len = 0;
42   *buffer = (char*)malloc(decodeLen+1);
43   FILE* stream = fmemopen(b64message, strlen(b64message), "r");
44  
45   b64 = BIO_new(BIO_f_base64());
46   bio = BIO_new_fp(stream, BIO_NOCLOSE);
47   bio = BIO_push(b64, bio);
48   BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
49   len = BIO_read(bio, *buffer, strlen(b64message));
50     //Can test here if len == decodeLen - if not, then return an error
51   (*buffer)[len] = '\0';
52  
53   BIO_free_all(bio);
54   fclose(stream);
55  
56   return (0); //success
57 }
58 
59 int main() {
60   //Encode To Base64
61   char* base64EncodeOutput;
62   char* pPlainText = "Hi, I'm fpzeng";
63   printf("Input plain text: %s\n", pPlainText);
64   Base64Encode(pPlainText, &base64EncodeOutput);
65   printf("Output (base64): %s\n", base64EncodeOutput);
66  
67   //Decode From Base64
68   char* base64DecodeOutput;
69   Base64Decode(base64EncodeOutput, &base64DecodeOutput);
70   printf("Output: %s\n", base64DecodeOutput);
71   
72   return(0);
73 }

 

Makefile 

.PHONY : clean
OPT=-O0
DEBUG= -g
CFLAGS=-Wall -fPIC $(XCFLAGS) $(INC) $(OPT) $(SO_DEF) $(DEBUG) $(DEF) 
INCLUDES = -I./ 
SRCS = base64.c 
OBJS = $(SRCS:.c=.o)
LIBS = -lssl -lcrypto -lm 

MAIN = base64 
all:    $(MAIN)
	@echo  $(MAIN) has been compiled

$(MAIN): $(OBJS) 
	$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
	@echo output: $(OBJS)
.c.o:
	$(CC) $(CFLAGS) $(INCLUDES) -c $<  -o $@
clean: @echo clean $(MAIN) $(OBJS) rm -fr $(MAIN) $(OBJS)

  

Python实现

posted @ 2014-12-25 11:57  fpzeng  阅读(953)  评论(0编辑  收藏  举报