通信加密
2.1 软件、通信加密的几种常用方案
2.1.1 异或位运算加密
优点:运算量小,速度极快 缺点:容易被破解
Python字符串异或的代码:
def xor(s, k):
return ''.join(chr(ord(i) ^ ord(j)) for i, j in zip(s, k))
-
zip
函数将传入的参数打包成tuple,然后返回由这些tuple组成的list,若两个参数长度不相等,那返回的list长度就由传入最短的那个元素长度决定; -
ord
则是将传入长度为1的字符串转化为ASCII值。
2.1.2 其他对称加密
对称加密算法有DES、AES、Blowfish等。
- DES:分CBC和ECB模式;在Python中,有pyDes库。
- AES:在Python中,有PyCrypto和PyAES库。
2.1.3 非对称加密
非对称密钥,是指一对加密密钥和解密密钥,用某用户密钥加密后所得的信息,只能用该用户的解密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。公开的密钥称为公钥,不公开的密钥称为私钥。
小结: 对称加密和非对称加密结合使用,可以达到安全性的最大化;使用物理介质的证书能够提供更高的安全性,如网银的U盾。
2.2 OpenSSL
OpenSSL开源库主要分为三个方面,SSL协议库(libssl)、应用程序(openssl)和密码算法库(libcrypto)。
安装OpenSSL库:
pip install pyOpenSSL
测试:
import socket, sys
from OpenSSL import SSL
context = SSL.Context(SSL.SSLv23_METHOD)
print "creating socket"
s_handle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl = SSL.Connection(context, s_handle)
print "Connecting..."
ssl.connect(("www.so.com", 443))
2.2.1 生成证书
OpenSSL提供的几种证书类型:
- PEM
- DER
- PFX
- JKS
- KDB
- CSR
- 6OCSP
- CER
- CRT
- KEY
- CRL
- SCEP
- PKCS7
- PKCS12
确定已经安装和编译完OpenSSL的所有程序和类库,确保已经生成了OpenSSL自带的命令行程序,并且设置完环境变量(OPENSSL_CONF),就可以开始制作证书了。
-
制作私钥:
openssl genrsa -out ca-key.pem 1024
-
通过这个pen文件来制作创建证书:
openssl req -new -out ca-req.csr -key ca-key.pem
-
接着会出现prompt对话框,按着它提示的内容输入即可(Windows下,extra属性直接回车跳过)。
-
生成自我签署的证书,有效期为10年:
openssl x509 -days 3650 -req -in ca-req.csr -out ca-cert.pem -signkey ca-key.pem
2.2.2 公钥和私钥的配置
配置私钥:
openssl genrsa -out folder/rsa_private_key.pem 1024
根据私钥生成配对的公钥:
openssl rsa -in folder/rsa_private_key.pem -pubout -out folder/rsa_public_key.pem
注:除了使用标准的OpenSSL之外,还可以使用Python程序来制作公钥和私钥。如M2Crypto类库。
2.3 SSL/TLS通信
SSL(Secure Socket Layer,安全套接层协议),是公钥和私钥的技术组合的安全网络通信协议。
SSL保证了网络通信的三个目标——隐秘、完整和认证。密文加密防止攻击,散列算法保证内容完整,利用证书保证客户端和服务端能认证对方的身份。
TLS是SSL的v3版本,TLS全称是Transport Layer Security,即传输层安全协议。
2.3.1 SSL/TLS连接
服务器部分:
# coding=utf-8
import socket
import ssl
import _ssl
detail = ssl.SSLContext(_ssl.PROTOCOL_TLSv1) # ssl.PROTOCOL_TLSv1
detail.load_cert_chain(certfile="cert.pem", keyfile="key.pem")
bindsocket = socket.socket()
bindsocket.bind(('127.0.0.1', 1234))
bindsocket.listen(5)
while 1:
conn, addr = bindsocket.accept()
stream = detail.wrap_socket(conn, server_side=True)
try:
do_someting(stream)
finally:
stream.shutdown(socket.SHUT_RDWR)
conn_stream.close()
客户端部分:
import socket
import ssl
s_handle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
detail = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
detail.check_hostname = True
detail.load_verify_locations('cert.pem')
ssl_sock = context.wrap_socket(s, server_hostname='test')
do_something with ssl_sock...
ssl_sock.close()
2.3.2 SSL/TLS HTTPS通信
HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer),即安全Socket层的HTTP协议。
HTTPS与HTTP的区别:
- 由于SSL/TLS协议,HTTPS需要CA证书。
- HTTPS具有SSL加密传输协议。
- HTTPS默认端口是443。
- 由于SSL/TLS协议,HTTPS具有身份认证和加密传输,安全性更高。
SSL/TLS服务器和客户端的握手过程如下:
- 浏览器向服务器传送客户端SSL协议版本号、加密算法类型、随机数,以及其他信息。
- 服务器向客户端传送SSL证书、协议版本号、加密算法类型、随机数以及其他相关信息。
- 客户端利用服务器传过来的信息验证服务器的合法性。若合法验证没有通过,连接将断开。
- 客户端随机产生一个“对称密码”,然后用服务器的公钥对其加密,将加密后的“预备密码”传给服务器。
- 若服务器要求客户端身份认证(可选),用户建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户端证书以及加密过的“预备密码”一起传给服务器。
- 若服务器要求客户端身份认证,服务器必须检验客户端证书和签名随机数的合法性。若检验没有通过,连接中断;若验证通过,服务器将用自己的私钥解开加密的“预备密码”,然后生成主密码(客户端也将通过同样的方法产生相同的主密码)。
- 服务器和客户端用相同的主密码,一个对称密钥用于SSL协议的加解密通信。同时在SSL通信过程中要完成数据通信的完整性,防止数据通信中的任何变化(被中间人攻击等)。
- 客户端向服务器发出信息,指明后面的数据通信将使用主密码为对称密钥,通知服务器的握手过程结束。
- 服务器向客户端发出信息,指明后面的数据通信将使用主密码为对称密钥,通知客户端的握手过程结束。
- SSL的握手部分结束,SSL安全通道的正式数据通信开始,客户端和服务器开始使用相同的对称密钥进行数据通信,同时进行通信完整性的检验。
HTTPS通信过程:
import httplib, ssl, urllib2, socket
class HTTPS(httplib.HTTPSConnection):
def __init__(self, *args, **kwargs):
httplib.HTTPSConnection.__init__(self, *args, **kwargs)
def connect(self):
sock = socket.create_connection((self.host, self.port), self.timeout)
if self._tunnel_host:
self.sock = sock
self._tunnel()
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3)
class HTTPS_Handle(urllib2.HTTPSHandler):
def https_open(self, req):
return self.do_open(HTTPS, req)
urllib2.install_opener(urllib2.build_opener(HTTPS_Handle()))
if __name__ == "__main__":
r = urllib2.urlopen("https://www.so.com")
2.4 其他加密方式
2.4.1 散列算法
散列是给文件或某个目标字符串通过算法形成一个特征签名字符串(指纹或称为摘要)。
散列算法有:
- CRC8、CRC16、CRC32
- MD2、MD4、MD5
- SHA1、SHA256、SHA384、SHA512
- RIPEMD、PANAMA、TIGER、ADLE32等
在Python中,可以使用hashlib库,下面通过打印查看这个库支持的散列算法。
import hashlib
print hashlib.algorithms_available
print hashlib.algorithms_guaranteed
尝试使用SHA1进行散列:
m = hashlib.sha1()
m.update(b'test string')
print m.hexdigest()
2.4.2 BASE64
BASE64把每三个8位字节转换为四个6位的字节,然后把6位再添两位高位0,组成四个8位的字节。
BASE64编码和解码:
import base64
a = "this is test"
b = base64.encoderstring(a)
print b
print base64.decoderstring(b)
2.4.3 多国语言
设置多国语言只需要在抬头加上#encoding:utf8
之类的标签即可。
在Windows平台用Python进行多国语言编码的时候,最好加上以下内容:
#!/user/bin/env python
# -*- coding: utf-8 -*-
import os, sys
reload(sys)
sys.setdefaultencoding('utf-8')