muchener's blogs

socket RSA加密通信

字数统计: 886阅读时长: 3 min
2016/09/01 Share

用python编写socket加密通信主要有两点,第一步是通过socket库实现socket通信,第二步将通信的内容使用pycrypto库进行RSA加解密操作。

step1:

socket通信原理图

可能不是一个客户端在登录,所以我们这里使用多线程,确保客户端相互不干扰。

下边是一个简单的聊天小程序。

客户端

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
26
27
28
29
30
31
32
#-*-encoding:utf-8 -*-
import socket,os,threading
class RecvMsg(threading.Thread):
def __init__(self,threadName,client):
threading.Thread.__init__(self)
self.name=threadName
self.client=client
def run(self):
while 1:
data = client.recv(1024)
if data:
print data
#如果有信息,就打印出来,这个主线程只需要做这个
else:
pass
client.close()
class SendMsg(threading.Thread):
def __init__(self,threadName,client):
threading.Thread.__init__(self)
self.name=threadName
self.client=client
def run(self):
while 1:
data=raw_input("")
self.client.sendall(data)
client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address=('127.0.0.1',12001)
client.connect(address)
s=SendMsg("msg1",client)
s.start() #调用start方法新建一个子线程,注意,run方法本身是单线程
w=RecvMsg("msg2",client)
w.start()

服务器端:

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
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
#-*-encoding:utf-8 -*-
import socket
import threading
import os
import Queue
msglist=Queue.Queue(maxsize = 0)
clientlist=[]
class HandleMsg(threading.Thread):
def __init__(self,threadName,conn):
threading.Thread.__init__(self)
self.name=threadName
self.conn=conn
self.alive=True
def broadcast(self):
msg=msglist.get()
print msg
for i in clientlist:
try:
i.sendall(msg)
except:
print self.name+" has disconnected"
clientlist.remove(i)
else:
pass
def stop(self):
self.alive=False
print self.name+" has disconnected"
def run(self):
while self.alive:
try:
data=self.conn.recv(1024)
except:
self.stop()
self.conn.close()
clientlist.remove(self.conn)
else:
msglist.put(self.name+" says:"+data)
self.broadcast()
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address=('',12001)
server.bind(address)
server.listen(30) #这里代表最多响应的连接个数
while 1:
conn, addr = server.accept()
(host,port)=addr
#这里使用host来获取连接的ip
#然后每次有人连接进来服务器就打印一个连接进来的消息
print host+" has connected into server"
clientlist.append(conn) #这里把每个连接的客户端加入一个列表
#广播的时候就直接遍历发送
HandleMsg(host,conn).start()

step2:加密(对1中的功能做部分修改)

秘钥产生过程

在消息处理的类中写一个秘钥产生的函数,在重写run方法的函数中先调用秘钥产生函数,实现客户与服务器间交换秘钥。

1
2
3
4
5
6
7
8
def crypmodel(self):
global random_generator
random_generator = Random.new().read
rsa = RSA.generate(1024, random_generator)
# generating key pair
private_pem = rsa.exportKey()
public_pem = rsa.publickey().exportKey()
return [private_pem,public_pem]

客户端向服务器发送消息

服务器向客户端发送消息

客户端向服务器发送消息,需要使用服务器端发来的公钥进行加密,服务器端使用自己的私钥进行解密。

1
2
3
4
5
6
7
8
9
10
11
#加密
def encrypto(self,txt,public_pemC):
rsakey = RSA.importKey(public_pemC)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
return base64.b64encode(cipher.encrypt(txt))
#解密
def decrypto(self,txt,private_pemS):
global random_generator
rsakey = RSA.importKey(private_pemS)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
return cipher.decrypt(base64.b64decode(txt), random_generator)

这里我是让服务器端去教学信息网,就是实现了一个客户端发送加密后的用户名密码给服务器端,服务器端接收用户名密码后进行用户登录,然后把查找的内容逐条加密发送给客户端。

–end—之前是客户端与服务器建立连接后,服务器将加密的公钥发给客户端,以后是客户端发送的用户名密码的密文以及解密的明文。

客户端首先接收密文并解密的结果

当然了,通信过程做好还要加上数字签名,但是只是为了完成小学期作业,所以就没有进行到这么繁琐的地步。

CATALOG
  1. 1. step1:
    1. 1.1. 客户端
    2. 1.2. 服务器端:
  2. 2. step2:加密(对1中的功能做部分修改)