通信加密

Posted by LudoArt on July 12, 2019

通信加密

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中,有PyCryptoPyAES库

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')