base64_encode base64_decode

Base64是一种用64个字符来表示任意二进制数据的方法

sqlite3使用

 

#include<stdio.h>
#include "base64.h"

int main(int argc, char *argv[])
{
char str[1024] = "xyz";
char key[1024];
char out[1024];

base64_encode((void *)str, sizeof(str), key);
printf("%s\n", key);

int len;
base64_decode((void *)key, &len, out);
printf("%s, len: %d\n", out, len);


return 0;
}

 

#ifndef __BASE64_H__
#define __BASE64_H__

void base64_encode(const char* input, int len, char *output);
void base64_decode(const char* input, int *len, char *output);

#endif

 

 

 

/*
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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

//#include "base64.h"

typedef enum
{
step_a, step_b, step_c, step_d
} base64_decodestep;

typedef struct
{
base64_decodestep step;
char plainchar;
} base64_decodestate;

typedef enum
{
step_A, step_B, step_C
} base64_encodestep;

typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;

static 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];
}

static void __base64_init_decodestate(base64_decodestate* state_in)
{
state_in->step = step_a;
state_in->plainchar = 0;
}

static 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;
}

/*
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
*/

const int CHARS_PER_LINE = 72;

static void __base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}

static char __base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}

static 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;
}

static 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;
}

void base64_encode(const char* input, int len, char *output)
{
/* set up a destination buffer large enough to hold the encoded data */
char* c = output;
/* store the number of bytes encoded by a single call */
int cnt = 0;
/* we need an encoder state */
base64_encodestate s;

/*---------- START ENCODING ----------*/
/* initialise the encoder state */
__base64_init_encodestate(&s);
/* gather data from the input and send it to the output */
cnt = __base64_encode_block(input, len, c, &s);
c += cnt;
/* since we have encoded the entire input string, we know that
there is no more input data; finalise the encoding */
cnt = __base64_encode_blockend(c, &s);
c += cnt;
/*---------- STOP ENCODING ----------*/

/* we want to print the encoded data, so null-terminate it: */
*c = 0;
}

void base64_decode(const char* input, int *len, char *output)
{
/* set up a destination buffer large enough to hold the encoded data */
/* keep track of our decoded position */
char* c = output;
/* store the number of bytes decoded by a single call */
int cnt = 0;
/* we need a decoder state */
base64_decodestate s;

/*---------- START DECODING ----------*/
/* initialise the decoder state */
__base64_init_decodestate(&s);
/* decode the input data */
cnt = __base64_decode_block(input, strlen(input), c, &s);
c += cnt;
/* note: there is no base64_decode_blockend! */
/*---------- STOP DECODING ----------*/

/* we want to print the decoded data, so null-terminate it: */
//*c = 0;
*len = cnt;
}

 

 

Base64是一种用64个字符来表示任意二进制数据的方法。

用记事本打开exejpgpdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让记事本这样的文本处理软件能处理二进制数据,就需要一个二进制到字符串的转换方法。Base64是一种最常见的二进制编码方法。

Base64的原理很简单,首先,准备一个包含64个字符的数组:

['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']

然后,对二进制数据进行处理,每3个字节一组,一共是3x8=24bit,划为4组,每组正好6个bit:

base64-encode

这样我们得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。

所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。

如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。

Python内置的base64可以直接进行base64的编解码:

>>> import base64
>>> base64.b64encode('binary\x00string')
'YmluYXJ5AHN0cmluZw=='
>>> base64.b64decode('YmluYXJ5AHN0cmluZw==')
'binary\x00string'

由于标准的Base64编码后可能出现字符+/,在URL中就不能直接作为参数,所以又有一种"url safe"的base64编码,其实就是把字符+/分别变成-_

>>> base64.b64encode('i\xb7\x1d\xfb\xef\xff')
'abcd++//'
>>> base64.urlsafe_b64encode('i\xb7\x1d\xfb\xef\xff')
'abcd--__'
>>> base64.urlsafe_b64decode('abcd--__')
'i\xb7\x1d\xfb\xef\xff'

还可以自己定义64个字符的排列顺序,这样就可以自定义Base64编码,不过,通常情况下完全没有必要。

Base64是一种通过查表的编码方法,不能用于加密,即使使用自定义的编码表也不行。

Base64适用于小段内容的编码,比如数字证书签名、Cookie的内容等。

由于=字符也可能出现在Base64编码中,但=用在URL、Cookie里面会造成歧义,所以,很多Base64编码后会把=去掉:

# 标准Base64:
'abcd' -> 'YWJjZA=='
# 自动去掉=:
'abcd' -> 'YWJjZA'

去掉=后怎么解码呢?因为Base64是把3个字节变为4个字节,所以,Base64编码的长度永远是4的倍数,因此,需要加上=把Base64字符串的长度变为4的倍数,就可以正常解码了。

请写一个能处理去掉=的base64解码函数:

>>> base64.b64decode('YWJjZA==')
'abcd'
>>> base64.b64decode('YWJjZA')
Traceback (most recent call last):
  ...
TypeError: Incorrect padding
>>> safe_b64decode('YWJjZA')
'abcd'

小结

Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。

 

posted on 2015-12-14 17:56  DayAfterDay  阅读(1215)  评论(0编辑  收藏  举报

导航