-
Notifications
You must be signed in to change notification settings - Fork 0
/
client_phase2.py
207 lines (157 loc) · 7.21 KB
/
client_phase2.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# -*- coding: utf-8 -*-
"""Client_phase2.ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/drive/179fXL8f_vtlwGei9LrrWe6geZIh94kOL
"""
!pip install ecpy
!pip install pycryptodome
import math
import timeit
import random
import sympy
import warnings
from random import randint, seed
import sys
from ecpy.curves import Curve,Point
from Crypto.Hash import SHA3_256, HMAC, SHA256
import requests
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util.Padding import pad
from Crypto.Util.Padding import unpad
import random
import re
import json
API_URL = 'http://cryptlygos.pythonanywhere.com'
#CRYPTOGRAPHY CS411 FALL 2020 TERM RPOJECT PHASE 2
#Developing software for receiving messages from other clients
#IMPLEMENTED BY DENIZ CANGI, GULSEN GORKEM KOSE
stuID = 25359
#GET THE CURVE, ORDER, FIELD AND GENERATOR
curve = Curve.get_curve('secp256k1')
q = curve.order
p = curve.field
P = curve.generator
sL = 7607314394506061677990466796842274315842801300199560769842840753281729479854
QCli_long = Point(0x8642a0854b673af6989e0d4e109228543dabb4bf989beb4ff7d9324947405d9e , 0x17508f7382c066dc1e92f58a1a6268aa8f1a2a6ab88fd1ff151ccf30ba307824, curve)
#server's long term key
QSer_long = Point(0xc1bc6c9063b6985fe4b93be9b8f9d9149c353ae83c34a434ac91c85f61ddd1e9 , 0x931bd623cf52ee6009ed3f50f6b4f92c564431306d284be7e97af8e443e69a8c, curve)
def SignSL(message):
k = Random.new().read(int(math.log(q-2,2)))
k = int.from_bytes(k, byteorder='big')%q
R = k*P
r = R.x % q
mr = bytes(message, 'utf-8')+ r.to_bytes((r.bit_length()+7)//8, byteorder = 'big')
hashVal = SHA3_256.new(mr)
h = int.from_bytes(hashVal.digest(), 'big') % q
s = (sL*h + k)%q
return s,h
def Decryption(ctext,key,nonce_len):
ctext = ctext.to_bytes((ctext.bit_length()+7)//8, byteorder = 'big')
cipher = AES.new(key, AES.MODE_CTR, nonce=ctext[0:nonce_len])
dtext = cipher.decrypt(ctext[nonce_len:])
decrypt_text = dtext.decode('utf-8')
return decrypt_text
#TO REGISTER FOR THE SECOND PHASE UNCOMMENT THIS PART:
'''
s, h = SignSL(str(stuID))
####Register Long Term Key
mes = {'ID': 25427, 'H': h, 'S': s, 'LKEY.X': QCli_long.x, 'LKEY.Y': QCli_long.y}
response = requests.put('{}/{}'.format(API_URL, "RegLongRqst"), json = mes)
print(response.json())
code = input()
mes = {'ID': 25427, 'CODE': code}
response = requests.put('{}/{}'.format(API_URL, "RegLong"), json = mes)
print(response.json())'''
#TO DELETE THE LONG TERM KEY UNCOMMENT THIS PART:
'''
###########DELETE LONG TERM KEY
# If you lost your long term key, you can reset it yourself with below code.
# First you need to send a request to delete it.
mes = {'ID': stuID}
response = requests.get('{}/{}'.format(API_URL, "RstLongRqst"), json = mes)
print(response.json())
code = input()
#Then server will send a verification code to your email.
# Send this code to server using below code
mes = {'ID': stuID, 'CODE': code}
response = requests.get('{}/{}'.format(API_URL, "RstLong"), json = mes)
#Now your long term key is deleted. You can register again.
'''
#RESET OF THE EPHEMERAL KEYS. UNCOMMENT THIS FOLLOWING BLOCK IF NECESSARY
"""
s, h = SignSL(str(stuID))
mes = {'ID': stuID, 'S': s, 'H': h}
response = requests.get('{}/{}'.format(API_URL, "RstEKey"), json = mes)
"""
#SEND 10 EPHEMERAL KEYS TO SERVER, UNCOMMENT THIS BLOCK TOO IF YOU RESET YOUR EPHEMERAL KEYS TO CREATE NEW ONES
"""
Dict = {} #dictionary of the ephemeral key id and the corresponding private ephemeral key
for i in range(10): #10 ephemeral key generations
sA = Random.new().read(int(math.log(q-1,2)))
sA = int.from_bytes(sA, byteorder='big') % q
Dict[i] = sA
ekey = sA*P
toMessage = str(ekey.x) + str(ekey.y)
s, h = SignSL(toMessage)
#send ephemeral key
mes = {'ID': stuID, 'KEYID': i , 'QAI.X': ekey.x, 'QAI.Y': ekey.y, 'Si': s, 'Hi': h}
response = requests.put('{}/{}'.format(API_URL, "SendKey"), json = mes)
"""
#this dictionary stores the id of the ephemeral key and the corresponding private ephemeral key, hardcoded version of the previous execution
Dict = {0: 11792772638721029306480823162017832851569923696708514029368926860767329905746, 1: 27308599728192970402781421904933335745367760576096560559181227907593300330437, 2: 102069585076159861923204661318409632029731040941772982247707986778937363054247, 3: 77679538587566325466761127346354624824318749129050671500059729709854042801335, 4: 52094853565591818146277167939007687227161580681201530813253877846261066430493, 5: 47810659490390423269679142685466380293326801372866765858904492504608580833070, 6: 80251253138960582496190417850735113693473055649252752051177318672993610847061, 7: 23785413435926486489807918509970244954307618358032686811352583615834893733374, 8: 95671704331674520576471950392454552441915450390400805017368388903692443159452, 9: 70787501422839710712268929399527673683104422531186848149937571006509945138764}
print("Dictionary that keeps the ephemeral private keys with the ID =", Dict)
print()
#We will get 5 messages from server, current set of messages will be stored inside listOfMessages
listOfMessages = []
for i in range(5):
s,h = SignSL(str(stuID))
#Receiving Messages
mes = {'ID_A': stuID, 'S': s, 'H': h}
response = requests.get('{}/{}'.format(API_URL, "ReqMsg"), json = mes)
listOfMessages.append(response.json())
print("List of messages received =", listOfMessages)
print()
#decrypt messages
for i in listOfMessages:
keyID = int(i.get('KEYID'))
message = i.get('MSG')
#ephemeral public key of the pseudo-client
QBj_x = i.get('QBJ.X')
QBj_y = i.get('QBJ.Y')
QBj = Point(QBj_x, QBj_y, curve)
sA = Dict[keyID]
T = sA * QBj
message_for_U = "NoNeedToRunAndHide"
U = str(T.x) + str(T.y) + message_for_U
hashVal= SHA3_256.new(bytes(U, 'utf-8'))
k_enc = hashVal.digest()
hashVal_ = SHA3_256.new(k_enc)
k_mac = hashVal_.digest()
#Whole message with nonce-message itself-hmac is converted into byte array
msg_bytes = message.to_bytes((message.bit_length() + 7)//8, byteorder= 'big')
#Last 32 bytes is the hmac
HMAC_extracted = msg_bytes[len(msg_bytes)-32:]
#First portion is the nonce and the message itself
message_withnonce = msg_bytes[:len(msg_bytes)-32]
#message without nonce to get the MAC of the message
message_without_nonce = msg_bytes[8:len(msg_bytes)-32]
#message in int format to decrypt it
message_int = int.from_bytes(message_withnonce, 'big')
#get the HMAC-SHA256 of the message with k_mac
HMAC_val = HMAC.new(k_mac, message_without_nonce, digestmod=SHA256)
hmac = HMAC_val.digest()
#if the mac computed and mac extracted from the message are the same then the message is authenticated
if hmac == HMAC_extracted:
print("The MAC of the message is verified, it is authentic!")
else:
print("The message is not authentic!")
decrypted_text = Decryption(message_int, k_enc, 8)
print("The decrypted message is:", decrypted_text)
#send decrypted messages to server
mes = {'ID_A': stuID, 'DECMSG': decrypted_text}
response = requests.put('{}/{}'.format(API_URL, "Checker"), json = mes)
print(response.json())
print()
print("Yes, we love the songs!")