def vanilla_dh(alice, bob):
p, g = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF, 2
alice_integer = pow(g, alice, p)
bob_integer = pow(g, bob, p)
alice_s = pow(bob_integer, alice, p)
bob_s = pow(alice_integer, bob, p)
if (alice_s == bob_s):
return alice_s
else:
return -1
print(vanilla_dh(45,5))
import hashlib
def int_to_bytes(x: int) -> bytes:
return x.to_bytes((x.bit_length() + 7) // 8, 'big')
def df_key():
common_secret = vanilla_dh(45, 5)
ans = hashlib.sha1(int_to_bytes(common_secret))
return ans.hexdigest()[:16]
print(df_key())
!pip install pycryptodome
from hashlib import md5
from base64 import b64decode
from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
def encrypt(key, iv, msg):
cipher = AES.new(key, AES.MODE_CBC, iv)
return b64encode(iv + cipher.encrypt(pad(msg.encode('utf-8'),16)))
def decrypt(key, iv, msg):
msg = b64decode(msg)
cipher = AES.new(key, AES.MODE_CBC, iv[:16])
return unpad(cipher.decrypt(msg[16:]), 16).decode('utf-8')
import random
import string
import os
BLOCK_SIZE = 16
key = os.urandom(BLOCK_SIZE)
iv = os.urandom(BLOCK_SIZE)
msg = ''.join(random.choice(string.ascii_lowercase) for i in range(1024))
assert decrypt(key, iv, encrypt(key, iv, msg)) == msg
import hashlib
import os
import random
class Agent:
def __init__(self, msg=None):
self.p, self.g = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF, 2
self.msg = msg
self.secret = None
#choose a random number from 0 to P (Zp)
self.private_key = random.randint(0, self.p)
self.block_size = 16
def send_public_data(self):
return self.p, self.g
def receive_public_data(self, p, g):
self.p, self.g = p, g
def send_public_key(self):
public_key = pow(self.g, self.private_key, self.p)
return public_key
def receive_public_key(self, public_key):
self.secret = pow(public_key, self.private_key, self.p)
def send_message(self):
iv = os.urandom(self.block_size)
ans = hashlib.sha1(int_to_bytes(self.secret))
ans = ans.hexdigest()[:16]
return [encrypt(str.encode(ans), iv, self.msg), iv]
def receive_message(self, arr):
ans = hashlib.sha1(int_to_bytes(self.secret))
ans = ans.hexdigest()[:16]
self.msg = decrypt(str.encode(ans), arr[1], arr[0])
alice = Agent("I'M 5UppER Kewl h4zKEr")
bob = Agent()
# Alice has da message, Bob doesn't
assert alice.msg
assert not bob.msg
# Negotiate parameters publicly
bob.receive_public_data(*alice.send_public_data())
alice.receive_public_data(*bob.send_public_data())
# Exchange keys publicly
bob.receive_public_key(alice.send_public_key())
alice.receive_public_key(bob.send_public_key())
# Pass da message
bob.receive_message(alice.send_message())
# Bob has it now
assert alice.msg == bob.msg
import hashlib
class MITM(Agent):
def __init__(self):
super().__init__()
self.public_keys = []
def receive_public_key(self, public_key):
if len(self.public_keys) == 0:
self.public_keys.append(pow(public_key, self.private_key, self.p))
else:
self.public_keys.append(pow(public_key, self.private_key, self.p))
def intercept_message(self, param):
ans = hashlib.sha1(int_to_bytes(self.public_keys[0]))
ans = ans.hexdigest()[:16]
self.msg = decrypt(str.encode(ans), param[1], param[0])
ans = hashlib.sha1(int_to_bytes(self.public_keys[1]))
ans = ans.hexdigest()[:16]
return [encrypt(str.encode(ans), param[1], self.msg), param[1]]
alice = Agent("I'M 5UppER Kewl h4zKEr")
bob = Agent()
mallory = MITM()
# Alice has da message, Bob doesn't
assert alice.msg
assert not bob.msg
# Negotiate parameters publicly
mallory.receive_public_data(*alice.send_public_data())
bob.receive_public_data(*mallory.send_public_data())
mallory.receive_public_data(*bob.send_public_data())
alice.receive_public_data(*mallory.send_public_data())
# Exchange keys publicly
mallory.receive_public_key(alice.send_public_key())
bob.receive_public_key(mallory.send_public_key())
mallory.receive_public_key(bob.send_public_key())
alice.receive_public_key(mallory.send_public_key())
# Pass da message
bob.receive_message(mallory.intercept_message(alice.send_message()))
# Bob has it now
assert bob.msg == alice.msg
# Mallory too
assert mallory.msg == alice.msg
import hashlib
class RsaAgent():
def __init__(self, p=13604067676942311473880378997445560402287533018336255431768131877166265134668090936142489291434933287603794968158158703560092550835351613469384724860663783, q = 20711176938531842977036011179660439609300527493811127966259264079533873844612186164429520631818559067891139294434808806132282696875534951083307822997248459, e=3):
self.p = p
self.q = q
self.e = e
self.n = self.p * self.q
self.mod = (self.p-1)*(self.q-1)
self.d = self.inv_mod(self.e, self.mod)
self.msg = None
def inv_mod(self, a, m):
return pow(a, -1, m)
def encrypt(self, msg, n, e):
msg = int.from_bytes(msg, "big")
enc_msg = pow(msg, e, n)
return int_to_bytes(enc_msg)
def decrypt(self, msg):
msg = int.from_bytes(msg, "big")
dc_msg = pow(msg, self.d, self.n)
self.msg = dc_msg
return int_to_bytes(self.msg)
def encrypt_int(self, msg, n, e):
enc_msg = pow(msg, e, n)
return enc_msg
def decrypt_int(self, msg):
dc_msg = pow(msg, self.d, self.n)
self.msg = dc_msg
return self.msg
def generate_message_hash(self, message):
return hashlib.sha1(message).digest()
def generate_signature(self, msg_sha1):
f_counter = self.n.bit_length()//8 - len(msg_sha1) - 3
output = bytes(b'\00\01') + f_counter*bytes(b'\xff') + (b'\00') + msg_sha1
return self.decrypt(output)
def verify_signature(self, signature, msg_sha1):
encrypted = bytes(b'\x00') + self.encrypt(signature, self.n, self.e)
#can not use this, cuz we need shitty implementation
#f_counter = self.n.bit_length()//8 - len(msg_sha1) - 3
index_0 = encrypted[2:].index(bytes(b'\00'))
if encrypted[0:2] != bytes(b'\00\01'):
return False
#can not check this or attack will not work :))
# elif encrypted[2:2+f_counter] != f_counter*bytes(b'\xff'):
# print("Error F ")
# return False
elif encrypted[index_0+3:index_0+3+len(msg_sha1)] != msg_sha1:
return False
else:
return True
def fake_signature(self, msg_sha1):
f_count = self.n.bit_length()//8 - len(msg_sha1) - 4
sig = bytes(b'\x00\x01\xFF\x00') + msg_sha1 + bytes(b'\xFF') * f_count
sig = int.from_bytes(sig, "big")
return int_to_bytes(cube_root(sig))
#int test
alice = RsaAgent()
bob = RsaAgent()
message = "I will not write crypto code myself, but defer to high-level libraries written by experts who took the right decisions for me".encode()
message = int.from_bytes(message, "big")
assert message == bob.decrypt_int(alice.encrypt_int(message, bob.n, bob.e))
#bytes test
message = "I will not write crypto code myself, but defer to high-level libraries written by experts who took the right decisions for me".encode()
dec_mess = bob.decrypt(alice.encrypt(message, bob.n, bob.e)).decode("utf-8")
dec_mess = dec_mess.replace('\x00', '').encode()
assert message == dec_mess
#inv mod test
desired = 701912218
got = alice.inv_mod(19, 1212393831)
assert desired == got
def cube_root(x):
#lower bound, upper bound, optimum
lb = 1
ub = 1
opt = 1
while True:
if (pow(ub, 3) > x):
lb = ub // 2
opt = (lb + ub) // 2
while True:
if (lb > ub):
opt += 1
return opt
elif (x < pow(opt, 3) and ub > opt):
ub = opt
elif (x > pow(opt, 3) and lb < opt):
lb = opt
else:
return opt
opt = (lb + ub) // 2
ub = ub * 2
def attack(n, data):
N = 1
M = 0
for i in n:
N = N * i
index = 0
for i in n:
n_i = N//i
u_i = pow(n_i, -1, i)
M += data[index]*u_i*n_i
index += 1
return cube_root(M % N)
b_1_n = 308094483823603810903696442694991560838673995175026581330398527365060379059931214870566035535078059134845491056106679782295356614575975024964662284250190710831424792978853027038158990368954064828273049799691851823086005766343351661763445261596090780306611840757601445364869357124442281554537422066165714122487
b_1_data = 121396776020296508256458685856635089642349817439957821340776895064539420154035389862044967327904154277489833213500525705528711346036511676132555472830761169586887328797714808543711273311853607446765355283967578274503431049942739076949891974171216163955572810555516316777223461354611156423758225311298114751267
b_2_n = 229802839958873960429014212527509329121966418346156524558277569103892314880721474252684944045045227010224005082496897195439078651931540669580498358073339412173305069050977806429679644343390197678371219899466862054282672829808529475411783273656232982525674608810303579866732080162570238502990351651356059118063
b_2_data = 207930425385164929012521517308549650563117055276489844000442568769649383955396158929771856767208190245084791910117179710949354675365204489992096177909221343865789835471484010314494214136443721482684951313272969071749306122106026945692512970477026564247376955415711107386067605976043804162085936275309805484570
b_3_n = 214503109709758534986937343647601262884007845518103602177230162826778895096786597995547041016608101558284737555880058425147368105078391303101918933851169996889482396568195279045298065436623206709443780317822800401358895478125539357008953665573509691019773614724713712472818592002624475962090183444119549182159
b_3_data = 116224107751422952071028663118525740166961241904713449198800906007216382050904333065471203236323254378229475477988741559445422914654576476911555251735045659167853297455785415754651696398238222223535347836130139914227538778403617018844270568046788591762423529893612421947994401324239061782662394755791186666797
n = [b_1_n, b_2_n, b_3_n]
data = [b_1_data, b_2_data, b_3_data]
m = attack(n, data)
print(int_to_bytes(m).decode("utf-8"))
p = 19480788016963928122154998009409704650199579180935803274714730386316184054417141690600073553930946636444075859515663914031205286780328040150640437671830139
q = 17796969605776551869310475203125552045634696428993510870214166498382761292983903655073238902946874986503030958347986885039275191424502139015148025375449097
e = 3
alice = RsaAgent(p, q, e)
message = b'Trust no one'
msg_sha1 = alice.generate_message_hash(message)
signature = alice.generate_signature(msg_sha1)
assert alice.verify_signature(signature, msg_sha1)
assert alice.verify_signature(alice.fake_signature(msg_sha1), msg_sha1)