Chinaunix首页 | 论坛 | 博客
  • 博客访问: 262885
  • 博文数量: 54
  • 博客积分: 1761
  • 博客等级: 上尉
  • 技术积分: 585
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-17 23:30
文章分类

全部博文(54)

文章存档

2013年(4)

2012年(7)

2011年(15)

2010年(28)

分类: Python/Ruby

2010-11-27 20:52:46

Base64编码,首先我们应该搞清楚,为什么里面有个64的字样呢?其实是因为该编码使用64个明文来编码任意 的二进制文件,它里面只使用了A-Z,a-z,0-9,+,/这64个字符,有“略懂”的同学就会说了,里面还有“=”号啊,不错,不过等号不属于编码字 符,而是填充字符。

    还有就是,为什么发明这么个编码呢,其实这个编码的原理是很简单的,“破解”也很容易,电子邮件刚出来的 时候,只传递英文字符,这没有问题,但是后来,中国人,日本人都要发email,这样问题就来了,因为这些字符有可能会被邮件服务器或者网关当成命令处 理,故必须得有一种编码来对邮件进行加密,但是加密的目的是为了能够使得一些原始的服务器不出问题(新得牛叉服务器已经能处理这些乱七八糟得情况了,不过 因为已经形成了一套规范,所以邮件还是得经过Base64编码才能传递),这样加密必须得简单(那搞个取反,异或加密吧,:-),还是没解决根本问题 咯),加密简单,这样客户端程序加密解密也快,又要是明文Ascii编码,这样Base64就诞生了。当初设计人员主要是考虑了两个问题:

1、加密算法复杂程度和效率
2、如何处理传输

    Base64基本都能满足,如果因为发一封邮件把CPU占到100%或者把内存给用完了,那就完全没必要了,编码之后只要普通人一眼看不出内容就行了。

    下面谈谈Base64的编码原理,按照RFC2045的定义,The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.我之前在网上查Base64的资料时,发现了一个很好的网站,
base64编码在线转换器 :, 大家对Base64感兴趣的话,可以去看看。Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前 面补两个0,形成8位一个字节的形式。6bit2进制能表示的最大数是2的6次方减一,刚好是64,这也是为什么是64个字符的原因,这样就需要一张映射 表,表如下:

The Base64 Alphabet


      Value Encoding  Value Encoding  Value Encoding  Value Encoding
           0 A            17 R            34 i            51 z
           1 B            18 S            35 j            52 0
           2 C            19 T            36 k            53 1
           3 D            20 U            37 l            54 2
           4 E            21 V            38 m            55 3
           5 F            22 W            39 n            56 4
           6 G            23 X            40 o            57 5
           7 H            24 Y            41 p            58 6
           8 I            25 Z            42 q            59 7
           9 J            26 a            43 r            60 8
          10 K            27 b            44 s            61 9
          11 L            28 c            45 t            62 +
          12 M            29 d            46 u            63 /
          13 N            30 e            47 v
          14 O            31 f            48 w         (pad) =
          15 P            32 g            49 x
          16 Q            33 h            50 y

    编码原理:将3个字节转换成4个字节((3 X 8)=24=(4X6)),先读入3个字节,每读一个字节,左移8位,再右移四次,每次6位,这样就有4个字节了。
    解码原理:将4个字节转换成3个字节,先读入4个6位(用或运算),每次左移6位,再右移3次,每次8位,这样就还原了。

    Base64将3个字节转变为4个字节,因此,编码后的代码量(以字节为单 位,下同)约比编码前的代码量多了1/3。如果代码量正好是3的整数倍,那么恰好多了1/3。但如果不是呢?这个时候“=”终于派上用场啦,当代码量不是 3的整数倍时,代码量/3的余数自然就是2或者1。转换的时候,结果不够6位的用0来补上相应的位置,之后再在6位的前面补两个0。转换完空出的结果就用 就用“=”来补位,总之要保证最后编码出来得字节数是4的倍数。

    原理也说了表也给,大家可以编码了哈……

    再说说python对Base64的支持,有个base64模块,专门干这个事情的,大家去看看就行了,直接贴点例子代码。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# utility @ Python
# Functions: Base64 编解码模块
# Created By MagicTong on 2008-07-16

import base64
import os
import StringIO

# encode,decode, encodestring,decodestring, b64encode,b64decode, urlsafe_b64decode,urlsafe_b64encode

class KBase64:
"""
Base64 编码和解码模块,用于对文件,字符串,URL的编解码
对base64的简单封装
"""

def __init__(self):
pass

def encodeFile(self, strFileName, strDecName):
"""
将一个文件的内容编码为Base64
"""

if not os.path.exists(strFileName):
return False

f1 = None
f2 = None
try:
f1 = open(strFileName, "r")
f2 = open(strDecName, "w")

base64.encode(f1, f2)

except Exception, e:
print e
if f1 != None:
f1.close()
if f1 != None:
f2.close()
return False

f1.close()
f2.close()
return True

def decodeFile(self, strFileName, strDecName):
"""
将一个Base64文件的内容解码
"""

if not os.path.exists(strFileName):
return False

f1 = None
f2 = None
try:
f1 = open(strFileName, "r")
f2 = open(strDecName, "w")

base64.decode(f1, f2)

except Exception, e:
print e
if f1 != None:
f1.close()
if f1 != None:
f2.close()
return False

f1.close()
f2.close()
return True

def encodeSting(self, strSrc):
"""
对字符串进行Base64编码
"""
try:
strDec = base64.encodestring(strSrc)
except Exception, e:
print e
return "", False

return strDec, True

def decodeSting(self, strSrc):
"""
将Base64字符串解码为源字符串
"""
try:
strDec = base64.decodestring(strSrc)
except Exception, e:
print e
return "", False

return strDec, True

if __name__ == "__main__":
baseObj = KBase64()
print baseObj.encodeSting("a")

    python还有专门处理邮件的编解码的email模块,更方便啊,大家先看一份邮件的源文件:

Received: from dbmail.kingsoft.com (192.168.8.252) by mail.kingsoft.cn
 (192.168.13.1) with Microsoft SMTP Server id 8.1.240.5; Mon, 3 Mar 2008
 10:52:20 +0800
Received: from unknown (HELO linyehui) ()  by localhost
 with SMTP; 3 Mar 2008 03:08:58 -0000
From: =?gb2312?B?wdbStrvU?= <>
To: =?gb2312?B?VG9uZ0xlaSBbza/A2l0=?= <>,
 =?gb2312?B?THVIb25neWFuZyBbwr266dH0XQ==?= <>,
 =?gb2312?B?THVZaXdhbmcgW8Ks0ubN+l0=?= <>,
 =?gb2312?B?TGluWWVodWkgW8HW0ra71F0=?= <>,
 =?gb2312?B?TGlKaWFuIFvA7r2jXQ==?= <>,
 =?gb2312?B?TGlEZWhvbmcgW8DutcK66l0=?= <>,
 =?gb2312?B?SmlhbmdXYW5nc2hlbmcgW72qzfrJ+l0=?= <>,
 =?gb2312?B?R2VuZ1poYW9oZSBbuaLV17rYXQ==?= <>,
 =?gb2312?B?RGVuZ1BlbmcgW7XLxfRd?= <>,
 =?gb2312?B?Q2hlbmdIdWkgW7PMu9Rd?= <>,
 =?gb2312?B?Q2hlblpoaXFpYW5nIFuzwta+x79d?= <>
Date: Mon, 3 Mar 2008 10:50:54 +0800
Subject: =?gb2312?B?W7vh0um8x8K8XTIwMDgwMzAz1ty1/LT6u+Ff0N7V/bDmsb4=?=
Thread-Topic: =?gb2312?B?W7vh0um8x8K8XTIwMDgwMzAz1ty1/LT6u+Ff0N7V/bDmsb4=?=
Thread-Index: Ach82ZpIBkzrq2yfQl2VA1yMdD4T2g==
Message-ID: <>
Accept-Language: zh-CN, en-US
Content-Language: zh-CN
X-MS-Exchange-Organization-AuthAs: Anonymous
X-MS-Exchange-Organization-AuthSource: mail.kingsoft.cn
X-MS-Has-Attach:
X-MS-Exchange-Organization-SenderIdResult: PermError
X-MS-Exchange-Organization-SCL: 1
X-MS-Exchange-Organization-PCL: 2
X-MS-Exchange-Organization-PRD: kingsoft.com
X-MS-TNEF-Correlator:
x-scanvirus: By EQAVSE AntiVirus Engine
x-scanresult: CLEAN
x-mailfrom: <>
x-rcptto: <>
x-fromip: 219.131.196.66
x-eqmanager-scaned: 1
x-eqauthuser: linyehui
x-received: unknown,219.131.196.66,20080303110858
received-spf: PermError (mail.kingsoft.cn: domain of
 used an invalid SPF mechanism)
Content-Type: text/plain; charset="gb2312"
Content-Transfer-Encoding: base64
MIME-Version: 1.0

yc/W3Lmk1/fX3L3ho7oNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLQ0KwdbStrvUDQqjsaGi1ti5ubXEzsi2qLmk1/cNCqOyoaLD3LGjobDR3tXV
w8WhsbCyyKu1urzTx7+5psTcsOaxvs/gudgNCqOzoaLHqNLGtPrC6w0Ko7Shote8sbi907Cy17DG
97W9sLLIq9bQ0MSjqMq1z9ZQcm94eaOpDQqzwta+x78NCqOxoaK/tLT6wusNCqOyoaLI7bz+1f3U
2tTL0NDEo7/pDQqjs6GisLLXsNTL0NC1yMSjv+m1xLLiytQNCqO0oaK199PDza/A2rXExKO/6cqx
o6zO9rm5yrGz9rTtDQqjtaGivMa7rqO6yrXP1qGhtffTw21zabXEyO28/tC21NgNCsDuvaMNCqOx
oaLKtc/WzfjVvsjP1qTR3cq+o8KjyKPPDQqjsqGita+/8s7KzOKjqLLpyv2+3cyrvsPBy7vhta+j
qQ0Ko7OhokhhbzEyM6Gi5dvTzsr9vt0oyKW19NbYuLTT0DHN8jEpDQqjtKGiTWFjZru5yqOjtM3y
tuDK/b7dw7uy6bW9o6zDu7Lptb21xNe8sbi808nP19S2r8nPsai5psTcDQrNr8DaDQqjsaGiRVhF
16qzybf+zvENCqOyoaLN6snG0K3S6crVyKFFWEUNCqOzoaLX1Mb0tq+zzNDyy9HL9w0Ko7ShorzG
u66jurDRtKu13bXEdmVjdG9ysvC31rPJw7vT0LD817C5/bXEyv2+3dTZtKu13aGjDQrA7r78DQqj
saGisNm2yLCyyKvW0NDEt6KyvA0Ko7Khornj1t2z9rLuDQqjs6GivMa7rqO6vdNpbmZvYyiy6dGv
oaLJz7GoKQ0Ko7ShorzGu66jurCyyKvW0NDEvObI3XZpc3RhDQqzzLvUDQqjsaGidHVvdHXPwtTY
xKO/6b3TyOsNCqOyoaLI7bz+udzA7bj3u/mxvrmmxNzN6rPJDQqjs6GisuLK1L27uPizwta+x78N
CqO0oaK/qrv6xvS2r727uPjNr8DaDQqjtaGisb7W3Lmk1/e7+bG+zeqzyaOsu7nT0Ly4uPZCVUcN
Cg0KDQoNCrG+1ty8xruuo7oNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLQ0Ko7GhokxZSCCwssir1tDQxNPrsLLXsMb31q685LXEtPrA7aGiyOe5
+9Kqus3N+NPOus/X97XEu7C7udKqsNHW2Lm5sOaxvrXE19S2r9eisuG3/s7xtci808nPDQqjsqGi
x7bN+NKztcRFWEUNCqOzoaLN+NKzo6iworbFo6kNCqO0oaLX9tDFz6LOxLz+tcS5pL7fDQoNCg0K
MjAwOC0wMy0wMw0KwdbStrvUDQo=

    很乱是吧,不知所云,hoho,但是解码很简单,解码代码如下:

# coding=utf-8

import email

fp = open("magicTong.eml", "r")
msg = email.message_from_file(fp) # 直接文件创建message对象,这个时候也会做初步的解码
subject = msg.get("subject") # 取信件头里的subject, 也就是主题

# 下面的三行代码只是为了解码象=?gbk?Q?=CF=E0=C6=AC?=这样的subject
h = email.Header.Header(subject)
dh = email.Header.decode_header(h)
subject = dh[0][0]
print "subject:", subject
print "from: ", email.utils.parseaddr(msg.get("from"))[1] # 取from
print "to: ", email.utils.parseaddr(msg.get("to"))[1] # 取to
print "Date: ", email.utils.parsedate(msg.get("Date"))

# 循环信件中的每一个mime的数据块
for par in msg.walk():
if not par.is_multipart(): # 这里要判断是否是multipart,是的话,里面的数据是无用的,至于为什么可以了解mime相关知识。
name = par.get_param("name") #如果是附件,这里就会取出附件的文件名
if name:
#有附件
# 下面的三行代码只是为了解码象=?gbk?Q?=CF=E0=C6=AC.rar?=这样的文件名
h = email.Header.Header(name)
dh = email.Header.decode_header(h)
fname = dh[0][0]
print '附件名:', fname
data = par.get_payload(decode=True) # 解码出附件数据,然后存储到文件中

try:
f = open(fname, 'wb') #注意一定要用wb来打开文件,因为附件一般都是二进制文件
except:
print '附件名有非法字符,自动换一个'
f = open('aaaa', 'wb')
f.write(data)
f.close()
else:
#不是附件,是文本内容
print par.get_payload(decode=True) # 解码出文本内容,直接输出来就可以了。

print '+'*60 # 用来区别各个部分的输出

fp.close()
<这段代码不知道是哪个老兄的啦,我很久之前从网上拷贝下来的,能用就行啦>

    假设上面那个email的名字是magicTong.eml。解码内容如下:

subject: [会议记录]20080303周迭代会_修正版本
from: 
to: 
Date:  (2008, 3, 3, 10, 50, 54, 0, 1, -1)
上周工作总结:

------------------------------------------------------

林叶辉

1、重构的稳定工作

2、密保“艳照门”安全岛加强功能版本相关

3、迁移代码

4、准备接安装器到安全中心(实现Proxy)

陈志强

1、看代码

2、软件正在运行模块

3、安装运行等模块的测试

4、调用童磊的模块时,析构时出错

5、计划:实现 调用msi的软件卸载

李剑

1、实现网站认证演示BHO

2、弹框问题(查数据太久了会弹)

3、Hao123、遨游数据(去掉重复有1万1)

4、Macf还剩4万多数据没查到,没查到的准备加上自动上报功能

童磊

1、EXE转成服务

2、完善协议收取EXE

3、自启动程序搜索

4、计划:把传递的vector拆分成没有包装过的数据再传递。

李军

1、百度安全中心发布

2、广州出差

3、计划:接infoc(查询、上报)

4、计划:安全中心兼容vista

程辉

1、tuotu下载模块接入

2、软件管理各基本功能完成

3、测试交给陈志强

4、开机启动交给童磊

5、本周工作基本完成,还有几个BUG

 

 

 

本周计划:

------------------------------------------------------

1、LYH 安全中心与安装器之间的代理、如果要和网游合作的话还要把重构版本的自动注册服务等加上

2、嵌网页的EXE

3、网页(阿杜)

4、做信息文件的工具

 

 

2008-03-03

林叶辉


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

    o(∩_∩)o...哈哈,很方便吧

阅读(11315) | 评论(0) | 转发(0) |
0

上一篇:Python自我评定

下一篇:说说Struct

给主人留下些什么吧!~~