58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
from pyrad.packet import Packet, random_generator
|
|
|
|
|
|
def salt_encrypt(packet: Packet, value: bytes) -> bytes:
|
|
length = struct.pack('B', len(value))
|
|
buf = length + value
|
|
buf += b'\x00' * (16 - (len(buf) % 16))
|
|
|
|
# First bit if the random value must be 1
|
|
random_value = 32768 + random_generator.randrange(0, 32767)
|
|
result = struct.pack('!H', random_value)
|
|
|
|
last = packet.authenticator + result
|
|
while buf:
|
|
cur_hash = md5_constructor(packet.secret + last).digest()
|
|
for b, h in zip(buf, cur_hash):
|
|
result += bytes([b ^ h])
|
|
last = result[-16:]
|
|
buf = buf[16:]
|
|
|
|
return result
|
|
|
|
|
|
def validate_chap_password(packet: Packet, password: bytes) -> bool:
|
|
# TODO:
|
|
challange = packet.get('CHAP-Challenge', packet.authenticator)
|
|
return chap_password == hashlib.md5(chapid + password + challenge).digest()
|
|
|
|
|
|
def validate_pap_password(packet: Packet, password: bytes) -> bool:
|
|
obf_pass = password_encode(packet, password)
|
|
return packet['Password'] == obf_pass
|
|
|
|
|
|
def password_encode(packet: Packet, password: bytes) -> bytes:
|
|
password += b'\x00' * (16 - (len(password) % 16))
|
|
return obfuscation_algorithm(packet, password)
|
|
|
|
|
|
def password_decode(packet: Packet, password: bytes) -> bytes:
|
|
decoded = obfuscation_algorithm(packet, password)
|
|
return decoded.rstrip(b'\x00')
|
|
|
|
|
|
def obfuscation_algorithm(packet: Packet, password: bytes) -> bytes:
|
|
result = b''
|
|
buf = password
|
|
last = packet.authenticator
|
|
|
|
while buf:
|
|
cur_hash = md5_constructor(packet.secret + last)
|
|
for b, h in zip(buf, cur_hash):
|
|
result += bytes([b ^ h])
|
|
(last, buf) = (buf[:16], buf[16:])
|
|
|
|
return result
|
|
|