/
client.py
98 lines (74 loc) · 2.53 KB
/
client.py
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
from Crypto import Random
from util import get_password, encrypt, decrypt
import socket
HOST, PORT = 'localhost', 31337
class CryptoClient:
def __init__(self, filename: str):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._filename = filename
def _get_key(self):
# EKE algorithm
client_key = Random.get_random_bytes(16)
password = get_password(self._filename)
ciphertext = encrypt(password, client_key)
self._send(ciphertext)
# Get session key double encrypted
ciphertext = self._recv(80)
ciphertext = decrypt(password, ciphertext)
self._key = decrypt(client_key, ciphertext)
# Check key
r_a = Random.get_random_bytes(16)
ciphertext = encrypt(self._key, r_a)
self._send(ciphertext)
ciphertext = self._recv(64)
r_ab = decrypt(self._key, ciphertext)
if r_ab[:16] != r_a:
raise ValueError('r_a invalid')
r_b = r_ab[16:]
ciphertext = encrypt(self._key, r_b)
self._send(ciphertext)
print('Secure connection established')
def connect(self, host: str, port: int):
self.socket.connect((host, port))
self._get_key()
self.socket.settimeout(1)
def _send(self, data: bytes):
self.socket.sendall(data)
def send(self, data: bytes):
ciphertext = encrypt(self._key, data)
print('sent', ciphertext)
self._send(ciphertext)
def _recv(self, size: int) -> bytes:
return self.socket.recv(size)
def recv(self) -> bytes:
data = b''
while True:
try:
tmp = self._recv(1024)
if not tmp:
break
data += tmp
except socket.timeout:
break
return data
def receive(self) -> bytes:
while True:
response = self.recv()
if response:
return decrypt(self._key, response)
def close(self):
self.socket.close()
def communicate(host, port, filename):
client = CryptoClient(filename)
client.connect(host, port)
try:
while True:
text = input('>: ')
client.send(text.encode())
response = client.receive()
print(response.decode())
finally:
client.close()
return
if __name__ == '__main__':
communicate(HOST, PORT, './password.txt')