mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-27 05:34:42 +01:00
crypt module refactor. need to be tested in py2
This commit is contained in:
parent
9379dd968d
commit
e21614b1b2
94
crypt.py
94
crypt.py
@ -10,50 +10,62 @@ 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"):
|
|
||||||
"""Given a key, given an iv, and message
|
|
||||||
do whatever operation asked in the operation field.
|
|
||||||
Operation will be checked for: "decrypt" and "encrypt" strings.
|
|
||||||
Returns the message encrypted/decrypted.
|
|
||||||
message must be a multiple by 16 bytes (for division in 16 byte blocks)
|
|
||||||
key must be 32 byte
|
|
||||||
iv must be 32 byte (it's not internally used in AES 256 ECB, but it's
|
|
||||||
needed for IGE)"""
|
|
||||||
|
|
||||||
if len(key) != 32:
|
class IGE:
|
||||||
raise ValueError("key must be 32 bytes long (was " +
|
def __init__(self, key, iv):
|
||||||
str(len(key)) + " bytes)")
|
if len(key) != 32:
|
||||||
if len(iv) != 32:
|
raise ValueError("key must be 32 bytes long (was " +
|
||||||
raise ValueError("iv must be 32 bytes long (was " +
|
str(len(key)) + " bytes)")
|
||||||
str(len(iv)) + " 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)
|
self.key = key
|
||||||
blocksize = cipher.block_size
|
self.iv = iv
|
||||||
if len(message) % blocksize != 0:
|
|
||||||
raise ValueError("message must be a multiple of 16 bytes (try adding " +
|
|
||||||
str(16 - len(message) % 16) + " bytes of padding)")
|
|
||||||
|
|
||||||
ivp = iv[0:blocksize]
|
self.cipher = AES.new(key, AES.MODE_ECB, iv)
|
||||||
ivp2 = iv[blocksize:]
|
|
||||||
|
|
||||||
ciphered = bytearray()
|
def encrypt(self, message):
|
||||||
|
return self._ige(message, operation="encrypt")
|
||||||
|
|
||||||
for i in range(0, len(message), blocksize):
|
def decrypt(self, message):
|
||||||
indata = message[i:i+blocksize]
|
return self._ige(message, operation="decrypt")
|
||||||
if operation == "decrypt":
|
|
||||||
xored = strxor(indata, ivp2)
|
|
||||||
decrypt_xored = cipher.decrypt(xored)
|
|
||||||
outdata = strxor(decrypt_xored, ivp)
|
|
||||||
ivp = indata
|
|
||||||
ivp2 = outdata
|
|
||||||
elif operation == "encrypt":
|
|
||||||
xored = strxor(indata, ivp)
|
|
||||||
encrypt_xored = cipher.encrypt(xored)
|
|
||||||
outdata = strxor(encrypt_xored, ivp2)
|
|
||||||
ivp = outdata
|
|
||||||
ivp2 = indata
|
|
||||||
else:
|
|
||||||
raise ValueError("operation must be either 'decrypt' or 'encrypt'")
|
|
||||||
|
|
||||||
ciphered.extend(outdata)
|
def _ige(self, message, operation="decrypt"):
|
||||||
return ciphered
|
"""Given a key, given an iv, and message
|
||||||
|
do whatever operation asked in the operation field.
|
||||||
|
Operation will be checked for: "decrypt" and "encrypt" strings.
|
||||||
|
Returns the message encrypted/decrypted.
|
||||||
|
message must be a multiple by 16 bytes (for division in 16 byte blocks)
|
||||||
|
key must be 32 byte
|
||||||
|
iv must be 32 byte (it's not internally used in AES 256 ECB, but it's
|
||||||
|
needed for IGE)"""
|
||||||
|
|
||||||
|
if len(message) % blocksize != 0:
|
||||||
|
raise ValueError("message must be a multiple of 16 bytes (try adding " +
|
||||||
|
str(16 - len(message) % 16) + " bytes of padding)")
|
||||||
|
|
||||||
|
blocksize = self.cipher.block_size
|
||||||
|
ivp = self.iv[0:blocksize]
|
||||||
|
ivp2 = self.iv[blocksize:]
|
||||||
|
|
||||||
|
ciphered = bytearray()
|
||||||
|
|
||||||
|
for i in range(0, len(message), blocksize):
|
||||||
|
indata = message[i:i+blocksize]
|
||||||
|
if operation == "decrypt":
|
||||||
|
xored = strxor(indata, ivp2)
|
||||||
|
decrypt_xored = self.cipher.decrypt(xored)
|
||||||
|
outdata = strxor(decrypt_xored, ivp)
|
||||||
|
ivp = indata
|
||||||
|
ivp2 = outdata
|
||||||
|
elif operation == "encrypt":
|
||||||
|
xored = strxor(indata, ivp)
|
||||||
|
encrypt_xored = self.cipher.encrypt(xored)
|
||||||
|
outdata = strxor(encrypt_xored, ivp2)
|
||||||
|
ivp = outdata
|
||||||
|
ivp2 = indata
|
||||||
|
else:
|
||||||
|
raise ValueError("operation must be either 'decrypt' or 'encrypt'")
|
||||||
|
ciphered.extend(outdata)
|
||||||
|
return ciphered
|
@ -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):
|
||||||
|
1
prime.py
1
prime.py
@ -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:
|
||||||
|
17
testing.py
17
testing.py
@ -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 ...
|
||||||
|
|
||||||
|
@ -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) + "'")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user