1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-27 07:34:41 +01:00

crypt module refactor. need to be tested in py2

This commit is contained in:
Anton Grigoryev 2015-03-16 17:59:59 +03:00
parent 9379dd968d
commit e21614b1b2
5 changed files with 69 additions and 62 deletions

View File

@ -10,7 +10,28 @@ from __future__ import print_function
from Crypto.Util.strxor import strxor from Crypto.Util.strxor import strxor
from Crypto.Cipher import AES from Crypto.Cipher import AES
def ige(message, key, iv, operation="decrypt"):
class IGE:
def __init__(self, key, iv):
if len(key) != 32:
raise ValueError("key must be 32 bytes long (was " +
str(len(key)) + " bytes)")
if len(iv) != 32:
raise ValueError("iv must be 32 bytes long (was " +
str(len(iv)) + " bytes)")
self.key = key
self.iv = iv
self.cipher = AES.new(key, AES.MODE_ECB, iv)
def encrypt(self, message):
return self._ige(message, operation="encrypt")
def decrypt(self, message):
return self._ige(message, operation="decrypt")
def _ige(self, message, operation="decrypt"):
"""Given a key, given an iv, and message """Given a key, given an iv, and message
do whatever operation asked in the operation field. do whatever operation asked in the operation field.
Operation will be checked for: "decrypt" and "encrypt" strings. Operation will be checked for: "decrypt" and "encrypt" strings.
@ -20,21 +41,13 @@ def ige(message, key, iv, operation="decrypt"):
iv must be 32 byte (it's not internally used in AES 256 ECB, but it's iv must be 32 byte (it's not internally used in AES 256 ECB, but it's
needed for IGE)""" needed for IGE)"""
if len(key) != 32:
raise ValueError("key must be 32 bytes long (was " +
str(len(key)) + " bytes)")
if len(iv) != 32:
raise ValueError("iv must be 32 bytes long (was " +
str(len(iv)) + " bytes)")
cipher = AES.new(key, AES.MODE_ECB, iv)
blocksize = cipher.block_size
if len(message) % blocksize != 0: if len(message) % blocksize != 0:
raise ValueError("message must be a multiple of 16 bytes (try adding " + raise ValueError("message must be a multiple of 16 bytes (try adding " +
str(16 - len(message) % 16) + " bytes of padding)") str(16 - len(message) % 16) + " bytes of padding)")
ivp = iv[0:blocksize] blocksize = self.cipher.block_size
ivp2 = iv[blocksize:] ivp = self.iv[0:blocksize]
ivp2 = self.iv[blocksize:]
ciphered = bytearray() ciphered = bytearray()
@ -42,18 +55,17 @@ def ige(message, key, iv, operation="decrypt"):
indata = message[i:i+blocksize] indata = message[i:i+blocksize]
if operation == "decrypt": if operation == "decrypt":
xored = strxor(indata, ivp2) xored = strxor(indata, ivp2)
decrypt_xored = cipher.decrypt(xored) decrypt_xored = self.cipher.decrypt(xored)
outdata = strxor(decrypt_xored, ivp) outdata = strxor(decrypt_xored, ivp)
ivp = indata ivp = indata
ivp2 = outdata ivp2 = outdata
elif operation == "encrypt": elif operation == "encrypt":
xored = strxor(indata, ivp) xored = strxor(indata, ivp)
encrypt_xored = cipher.encrypt(xored) encrypt_xored = self.cipher.encrypt(xored)
outdata = strxor(encrypt_xored, ivp2) outdata = strxor(encrypt_xored, ivp2)
ivp = outdata ivp = outdata
ivp2 = indata ivp2 = indata
else: else:
raise ValueError("operation must be either 'decrypt' or 'encrypt'") raise ValueError("operation must be either 'decrypt' or 'encrypt'")
ciphered.extend(outdata) ciphered.extend(outdata)
return ciphered return ciphered

View File

@ -7,9 +7,7 @@ Created on Tue Sep 2 19:26:15 2014
""" """
from binascii import crc32 as originalcrc32 from binascii import crc32 as originalcrc32
MIN_SUPPORTED_PY3_VERSION = (3, 2, 0) MIN_SUPPORTED_PY3_VERSION = (3, 2, 0)
from sys import version_info import numbers
if version_info >= MIN_SUPPORTED_PY3_VERSION: #py3 has no long
long = int
def crc32(data): def crc32(data):
return originalcrc32(data) & 0xffffffff return originalcrc32(data) & 0xffffffff
from datetime import datetime from datetime import datetime
@ -111,7 +109,7 @@ def serialize_param(bytes_io, type_, value):
assert isinstance(value, int) assert isinstance(value, int)
bytes_io.write(struct.pack('<i', value)) bytes_io.write(struct.pack('<i', value))
elif type_ == "long": elif type_ == "long":
assert (isinstance(value, long) or isinstance(value, int)) # Py2 can be both assert isinstance(value, numbers.Real)
bytes_io.write(struct.pack('<q', value)) bytes_io.write(struct.pack('<q', value))
elif type_ in ["int128", "int256"]: elif type_ in ["int128", "int256"]:
assert isinstance(value, bytes) assert isinstance(value, bytes)
@ -120,13 +118,11 @@ def serialize_param(bytes_io, type_, value):
l = len(value) l = len(value)
if l < 254: # short string format if l < 254: # short string format
bytes_io.write(struct.pack('<b', l)) # 1 byte of string bytes_io.write(struct.pack('<b', l)) # 1 byte of string
#bytes_io.write(int.to_bytes(l, 1, 'little')) # 1 byte of string
bytes_io.write(value) # string bytes_io.write(value) # string
bytes_io.write(b'\x00'*((-l-1) % 4)) # padding bytes bytes_io.write(b'\x00'*((-l-1) % 4)) # padding bytes
else: else:
bytes_io.write(b'\xfe') # byte 254 bytes_io.write(b'\xfe') # byte 254
bytes_io.write(struct.pack('<i', l)[:3]) # 3 bytes of string bytes_io.write(struct.pack('<i', l)[:3]) # 3 bytes of string
#bytes_io.write(int.to_bytes(l, 3, 'little')) # 3 bytes of string
bytes_io.write(value) # string bytes_io.write(value) # string
bytes_io.write(b'\x00'*(-l % 4)) # padding bytes bytes_io.write(b'\x00'*(-l % 4)) # padding bytes
@ -177,6 +173,7 @@ def deserialize(bytes_io, type_=None, subtype=None):
x[arg['name']] = deserialize(bytes_io, type_=arg['type'], subtype=arg['subtype']) x[arg['name']] = deserialize(bytes_io, type_=arg['type'], subtype=arg['subtype'])
return x return x
class Session: class Session:
""" Manages TCP Transport. encryption and message frames """ """ Manages TCP Transport. encryption and message frames """
def __init__(self, ip, port): def __init__(self, ip, port):

View File

@ -18,6 +18,7 @@ def primesbelow(N):
smallprimeset = set(primesbelow(100000)) smallprimeset = set(primesbelow(100000))
_smallprimeset = 100000 _smallprimeset = 100000
def isprime(n, precision=7): def isprime(n, precision=7):
# http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time # http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
if n == 1 or n % 2 == 0: if n == 1 or n % 2 == 0:

View File

@ -43,10 +43,6 @@ print("PQ = %d\np = %d, q = %d" % (PQ, p, q))
P_bytes = struct.pack('>i', p) P_bytes = struct.pack('>i', p)
Q_bytes = struct.pack('>i', q) Q_bytes = struct.pack('>i', q)
# print("p.bit_length()//8+1: " + str(p.bit_length()//8+1)) # 4
# print("q.bit_length()//8+1: " + str(q.bit_length()//8+1)) # 4
# P_bytes = int.to_bytes(p, p.bit_length()//8+1, 'big')
# Q_bytes = int.to_bytes(q, q.bit_length()//8+1, 'big')
f = open('rsa.pub', 'r') f = open('rsa.pub', 'r')
key = RSA.importKey(f.read()) key = RSA.importKey(f.read())
@ -78,8 +74,6 @@ z = Session.method_call('req_DH_params',
encrypted_data=encrypted_data) encrypted_data=encrypted_data)
encrypted_answer = z['encrypted_answer'] encrypted_answer = z['encrypted_answer']
print("encrypted_answer:")
print(encrypted_answer.__repr__())
tmp_aes_key = SHA.new(new_nonce + server_nonce).digest() + SHA.new(server_nonce + new_nonce).digest()[0:12] tmp_aes_key = SHA.new(new_nonce + server_nonce).digest() + SHA.new(server_nonce + new_nonce).digest()[0:12]
tmp_aes_iv = SHA.new(server_nonce + new_nonce).digest()[12:20] + SHA.new(new_nonce + new_nonce).digest() + new_nonce[0:4] tmp_aes_iv = SHA.new(server_nonce + new_nonce).digest()[12:20] + SHA.new(new_nonce + new_nonce).digest() + new_nonce[0:4]
@ -91,8 +85,11 @@ print("\ntmp_aes_iv:")
mtproto.vis(tmp_aes_iv) mtproto.vis(tmp_aes_iv)
print(tmp_aes_iv.__repr__()) print(tmp_aes_iv.__repr__())
decrypted_answer = crypt.ige(encrypted_answer, tmp_aes_key, tmp_aes_iv) crypter = crypt.IGE(tmp_aes_key, tmp_aes_iv)
print("decrypted_answer is:")
print(decrypted_answer.__repr__()) answer_with_hash = crypter.decrypt(encrypted_answer)
mtproto.vis(decrypted_answer[20:]) # To start off BA0D89 ...
answer_hash = answer_with_hash[:20]
answer = answer_with_hash[20:]
mtproto.vis(answer) # To start off BA0D89 ...

View File

@ -27,10 +27,10 @@ print("With key for AES 256 ECB: '" + str(aes_key) + "'")
# Initialization Vector must be 32 bytes # Initialization Vector must be 32 bytes
aes_iv = b'01234567890123456789012345678901' aes_iv = b'01234567890123456789012345678901'
print("And initialization vector: '" + str(aes_iv) + "'") print("And initialization vector: '" + str(aes_iv) + "'")
encrypted_msg = ige(msg_to_encrypt_padded, aes_key, aes_iv, operation="encrypt") encrypted_msg = _ige(msg_to_encrypt_padded, aes_key, aes_iv, operation="encrypt")
print("\nEncrypted msg: '" + str(encrypted_msg) + "'") print("\nEncrypted msg: '" + str(encrypted_msg) + "'")
print("In hex: " + encrypted_msg.__repr__()) print("In hex: " + encrypted_msg.__repr__())
decrypted_msg = ige(encrypted_msg, aes_key, aes_iv, operation="decrypt") decrypted_msg = _ige(encrypted_msg, aes_key, aes_iv, operation="decrypt")
print("\nDecrypted msg: '" + str(decrypted_msg) + "'") print("\nDecrypted msg: '" + str(decrypted_msg) + "'")
print("In hex: " + decrypted_msg.__repr__()) print("In hex: " + decrypted_msg.__repr__())
@ -44,7 +44,7 @@ msg_not_multiple_of_16 = "6bytes"
print("Trying to encrypt: '" + msg_not_multiple_of_16 + print("Trying to encrypt: '" + msg_not_multiple_of_16 +
"' of size: " + str(len(msg_not_multiple_of_16))) "' of size: " + str(len(msg_not_multiple_of_16)))
try: try:
encrypted_msg = ige(msg_not_multiple_of_16, aes_key, aes_iv, operation="encrypt") encrypted_msg = _ige(msg_not_multiple_of_16, aes_key, aes_iv, operation="encrypt")
except ValueError as ve: except ValueError as ve:
print(" Correctly got ValueError: '" + str(ve) + "'") print(" Correctly got ValueError: '" + str(ve) + "'")
@ -52,7 +52,7 @@ except ValueError as ve:
aes_key_not_32_bytes = b'0123456789' aes_key_not_32_bytes = b'0123456789'
print("Trying to use key: '" + str(aes_key_not_32_bytes) + "'") print("Trying to use key: '" + str(aes_key_not_32_bytes) + "'")
try: try:
encrypted_msg = ige(msg_to_encrypt_padded, aes_key_not_32_bytes, aes_iv, operation="encrypt") encrypted_msg = _ige(msg_to_encrypt_padded, aes_key_not_32_bytes, aes_iv, operation="encrypt")
except ValueError as ve: except ValueError as ve:
print(" Correctly got ValueError: '" + str(ve) + "'") print(" Correctly got ValueError: '" + str(ve) + "'")
@ -60,7 +60,7 @@ except ValueError as ve:
iv_key_not_32_bytes = b'0123456789' iv_key_not_32_bytes = b'0123456789'
print("Trying to use iv: '" + str(iv_key_not_32_bytes) + "'") print("Trying to use iv: '" + str(iv_key_not_32_bytes) + "'")
try: try:
encrypted_msg = ige(msg_to_encrypt_padded, aes_key, iv_key_not_32_bytes, operation="encrypt") encrypted_msg = _ige(msg_to_encrypt_padded, aes_key, iv_key_not_32_bytes, operation="encrypt")
except ValueError as ve: except ValueError as ve:
print(" Correctly got ValueError: '" + str(ve) + "'") print(" Correctly got ValueError: '" + str(ve) + "'")