赞
踩
关于base64,百度百科给出的解释是:
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。
Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读。
Base64由于以上优点被广泛应用于计算机的各个领域,然而由于输出内容中包括两个以上“符号类”字符(+, /, =),不同的应用场景又分别研制了Base64的各种“变种”。为统一和规范化Base64的输出,Base62x被视为无符号化的改进版本。
base64中的这64个可打印字符包括小写的
a
−
z
a-z
a−z和大写的
A
−
Z
A-Z
A−Z,依旧数字
0
−
9
0-9
0−9以及两个符号
“
+
"
和
“
/
"
“+"和“/"
“+"和“/"。选择64这个数字是因为64是2的6次方,正好可以用6位二进制编号,所以这64个字符在这里的编号不同于在ASCII中的编号了,应该为:
要先明确,base64的加密对象是二进制串
加密过程是:将三个字节 (共3*8=24位) 的二进制转换为四个字符
例如:
原来的二进制数是:1111 1111, 1111 1111, 1111 1111 (二进制)
转换后 0011 1111, 0011 1111, 0011 1111, 0011 1111 (二进制)
十进制为:63,63,63,63
对应上面码表的字符为
/
/
/
/
////
所以上面的24位编码,编码后的Base64值为
/
/
/
/
////
再来一个例子:
原来的二进制数是:1010 1101,1011 1010,0111 0110(二进制)
转换后 0010 1011, 0001 1011 ,0010 1001 ,0011 0110(二进制)
十进制为:43 27 41 54
对应上面码表的字符为
r
b
p
2
rbp2
rbp2
所以上面的24位编码,编码后的Base64值为
r
b
p
2
rbp2
rbp2
解码同理,把
r
b
q
2
rbq2
rbq2的二进制位连接上再重组得到三个8位值,得出原码。
base加密在python中可以直接调用库:base64
,例如:
(知道Base是对二进制数进行加密的,所以在对字母进行加密是就需要先将字母转化为数字)
import base64
s = 'a'
s1 = base64.b64encode(s.encode())
print(s1)
# b'YQ=='
s = 'ab'
s1 = base64.b64encode(s.encode())
print(s1)
# b'YWI='
// base64.cpp #include <iostream> #include <windows.h> #include "Base64.h" using namespace std; char *base64_encode(const char* data, int data_len) { //int data_len = strlen(data); int prepare = 0; int ret_len; int temp = 0; char *ret = NULL; char *f = NULL; int tmp = 0; char changed[4]; int i = 0; ret_len = data_len / 3; temp = data_len % 3; if (temp > 0) { ret_len += 1; } ret_len = ret_len*4 + 1; ret = (char *)malloc(ret_len); if ( ret == NULL) { printf("No enough memory.\n"); exit(0); } memset(ret, 0, ret_len); f = ret; while (tmp < data_len) { temp = 0; prepare = 0; memset(changed, '\0', 4); while (temp < 3) { //printf("tmp = %d\n", tmp); if (tmp >= data_len) { break; } prepare = ((prepare << 8) | (data[tmp] & 0xFF)); tmp++; temp++; } prepare = (prepare<<((3-temp)*8)); //printf("before for : temp = %d, prepare = %d\n", temp, prepare); for (i = 0; i < 4 ;i++ ) { if (temp < i) { changed[i] = 0x40; // 瀵瑰簲鐮佽〃涓殑 '=' } else { changed[i] = (prepare>>((3-i)*6)) & 0x3F; } *f = base[changed[i]]; //printf("%.2X", changed[i]); f++; } } *f = '\0'; return ret; } static char find_pos(char ch) { char *ptr = (char*)strrchr(base, ch);//the last position (the only) in base[] return (ptr - base); } char *base64_decode(const char *data, int data_len) { int ret_len = (data_len / 4) * 3; int equal_count = 0; char *ret = NULL; char *f = NULL; int tmp = 0; int temp = 0; int prepare = 0; int i = 0; if (*(data + data_len - 1) == '=') { equal_count += 1; } if (*(data + data_len - 2) == '=') { equal_count += 1; } if (*(data + data_len - 3) == '=') {//seems impossible equal_count += 1; } switch (equal_count) { case 0: ret_len += 4;//3 + 1 [1 for NULL] break; case 1: ret_len += 4;//Ceil((6*3)/8)+1 break; case 2: ret_len += 3;//Ceil((6*2)/8)+1 break; case 3: ret_len += 2;//Ceil((6*1)/8)+1 break; } ret = (char *)malloc(ret_len); if (ret == NULL) { printf("No enough memory.\n"); exit(0); } memset(ret, 0, ret_len); f = ret; while (tmp < (data_len - equal_count)) { temp = 0; prepare = 0; while (temp < 4) { if (tmp >= (data_len - equal_count)) { break; } prepare = (prepare << 6) | (find_pos(data[tmp])); temp++; tmp++; } prepare = prepare << ((4-temp) * 6); for (i=0; i<3 ;i++ ) { if (i == temp) { break; } *f = (char)((prepare>>((2-i)*8)) & 0xFF); f++; } } *f = '\0'; return ret; } int main() { char text[200]; printf("请输入待加密字符:"); int i=0; do { scanf("%s",&text[i]); i++; }while(getchar()!='\n'); printf("%s\n", base64_encode(text, strlen(text))); return 0; }
// base64.h
#ifndef BASE64_H
#define BASE64_H
const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
char* base64_encode(const char* data, int data_len);
char *base64_decode(const char* data, int data_len);
#endif
利用库
import base64
s = input()
a = base64.b64encode(s.decode())
print(a)
原理实现
class MyBase64(): base64_dict = {} string_temp = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' '0123456789+/') ascii_string = ''.join([chr(i) for i in range(4, 2 ** 7 - 1)]) def __init__(self, string): # 初始化,创建 base64 编码字典 self.string = string for i in range(2 ** 6): self.base64_dict[i] = self.string_temp[i] def convert(self): # base64 编码过程 # 编码 string_encode_byte = self.string.encode('utf-8') # 十进制化 string_digit_list = list(string_encode_byte) # 二进制化 + 0 填充 string_bin_list = [] for item in string_digit_list: string_bin_list.append(str(bin(item))[2:].zfill(8)) # 字符串合并 string_sum = ''.join(string_bin_list) # 6 的倍数,不足 0 填充 string_fill = self.fillIt(string_sum, factor=6, item='0') # 切片,6位一个单位 string_bin_list2 = self.splitIt(string_fill, bits=6) # 十进制化 string_digit_list2 = [] for item in string_bin_list2: string_digit_list2.append(int(item, 2)) # 查表 string_base64_list = [] for item in string_digit_list2: string_base64_list.append(self.base64_dict[item]) # 拼接 string_sum2 = ''.join(string_base64_list) # 4 的倍数,不足填充 = string_convert = self.fillIt(string_sum2, factor=4, item='=') return string_convert def fillIt(self, string, factor, item): """ 指定倍数填充指定字符 string:原字符串 factor:倍数 item:填充字符 """ length = len(string) remainder = length % factor if remainder: times = factor - remainder string = string + times * item return string def splitIt(self, string, bits): """ 指定位数切片 string:原字符串 bits:每次切片数量 """ length = len(string) new_list = [] for i in range(bits, length + 1, bits): new_list.append(string[i - bits:i]) remain = length % bits if remain != 0: new_list.append(string[-remain:]) return new_list if __name__ == '__main__': string = input() myBase64 = MyBase64(string) enc_string = myBase64.convert() print("测试字符串:{}".format(string)) print("base64:{}".format(enc_string))
base64之所以可以隐藏信息,便是在于在解密过程中,在解码的第3步中,会有部分数据被丢弃(即不会影响解码结果),这些数据正是在编码过程中补的0。也就是说,如果在编码过程中不全用0填充,而是用其他的数据填充,仍然可以正常编码解码,因此这些位置可以用于隐写。
解开隐写的方法就是将这些不影响解码结果的位提取出来组成二进制串(一行 base64 最多有 2 个等号, 也就是有 22 位的可隐写位.),然后转换成ASCII字符串。这就是为什么出base64隐写时会有很多大段 base64 的原因
def get_base64_diff_value(s1, s2): base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' res = 0 for i in xrange(len(s2)): if s1[i] != s2[i]: return abs(base64chars.index(s1[i]) - base64chars.index(s2[i])) return res def solve_stego(): with open('shy.txt', 'rb') as f: file_lines = f.readlines() bin_str = '' for line in file_lines: steg_line = line.replace('\n', '') norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '') diff = get_base64_diff_value(steg_line, norm_line) print diff pads_num = steg_line.count('=') if diff: bin_str += bin(diff)[2:].zfill(pads_num * 2) else: bin_str += '0' * pads_num * 2 print goflag(bin_str) def goflag(bin_str): res_str = '' for i in xrange(0, len(bin_str), 8): res_str += chr(int(bin_str[i:i + 8], 2)) return res_str if __name__ == '__main__': solve_stego()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。