18,7 → 18,7 |
""" |
# Relevation Password Printer |
# |
# Copyright (c) 2011,2012,2013 Toni Corvera |
# Copyright (c) 2011,2012,2013,2014 Toni Corvera |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
72,7 → 72,7 |
__author__ = 'Toni Corvera' |
__date__ = '$Date$' |
__revision__ = '$Rev$' |
__version_info__ = ( 1, 2 , 1 ) # Note: For x.y.0, only x and y are kept |
__version_info__ = ( 1, 3 ) #, 0 ) # Note: For x.y.0, only x and y are kept |
__version__ = '.'.join(map(str, __version_info__)) |
RELEASE=True |
|
279,7 → 279,7 |
return bool(st.st_mode & stat.S_IROTH) |
|
def load_config(): |
''' Load configuration file is one is found |
''' Load configuration file if one is found |
load_config() -> ( str file, str pass ) |
''' |
cfg = os.path.join(os.path.expanduser('~'), '.relevation.conf') |
309,29 → 309,62 |
printe('Configuration file (~/.relevation.conf) is not readable!') |
return ( fl, pw, mode ) |
|
def decrypt_gz(key, cipher_text): |
''' Decrypt cipher_text using key. |
decrypt(str, str) -> cleartext (gzipped xml) |
|
This function will use the underlying, available, cipher module. |
''' |
if USE_PYCRYPTO: |
# Extract IV |
c = AES.new(key) |
iv = c.decrypt(cipher_text[12:28]) |
# Decrypt data, CBC mode |
c = AES.new(key, AES.MODE_CBC, iv) |
ct = c.decrypt(cipher_text[28:]) |
else: |
# Extract IV |
c = rijndael.Rijndael(key, keySize=len(key), padding=noPadding()) |
iv = c.decrypt(cipher_text[12:28]) |
# Decrypt data, CBC mode |
bc = rijndael.Rijndael(key, keySize=len(key), padding=noPadding()) |
c = cbc.CBC(bc, padding=noPadding()) |
ct = c.decrypt(cipher_text[28:], iv=iv) |
return ct |
class DataReaderV1(object): |
def _decrypt_compressed_data(self, key, cipher_text): |
''' Decrypt cipher_text using key. |
decrypt(str, str) -> cleartext (gzipped xml) |
|
This function will use the underlying, available, cipher module. |
''' |
# Old format: |
# [0:12) 12B header: "rvl" 0x00, 0x01, 0x00 |
# [12:28) 16B ECB encrypted CBC IV |
# [28:] encrypted data |
if USE_PYCRYPTO: |
# Extract IV |
c = AES.new(key) |
iv = c.decrypt(cipher_text[12:28]) |
# Decrypt data, CBC mode |
c = AES.new(key, AES.MODE_CBC, iv) |
ct = c.decrypt(cipher_text[28:]) |
else: |
# Extract IV |
c = rijndael.Rijndael(key, keySize=len(key), padding=noPadding()) |
iv = c.decrypt(cipher_text[12:28]) |
# Decrypt data, CBC mode |
bc = rijndael.Rijndael(key, keySize=len(key), padding=noPadding()) |
c = cbc.CBC(bc, padding=noPadding()) |
ct = c.decrypt(cipher_text[28:], iv=iv) |
return ct |
def get_xml(self, data, password): |
# Pad password |
password += (chr(0) * (32 - len(password))) |
# Decrypt. Decrypted data is compressed |
cleardata_gz = self._decrypt_compressed_data(password, data) |
# Length of data padding |
padlen = ord(cleardata_gz[-1]) |
# Decompress actual data (15 is wbits [ref3] DON'T CHANGE, 2**15 is the (initial) buf size) |
return zlib.decompress(cleardata_gz[:-padlen], 15, 2**15) |
|
class DataReader(object): |
def __init__(self, filename, data): |
self._impl = None |
self._data = data |
self._check_header(filename) |
def _check_header(self, filename): |
header = self._data[0:12] |
magic = header[0:4] |
if magic != "rvl\x00": |
raise IOError('File \'%s\' not in the correct format' % filename) |
data_version = header[4] |
app_version = header[6:9] |
if data_version == '\x01': |
self._impl = DataReaderV1() |
else: |
raise IOError('File \'%s\' is in a newer, unsupported, data format' % filename) |
def get_xml(self, password): |
return self._impl.get_xml(self._data, password) |
|
def main(argv): |
datafile = None |
password = None |
343,7 → 376,7 |
dump_xml = False |
mode = None |
|
printe('Relevation v%s, (c) 2011-2013 Toni Corvera\n' % __version__) |
printe('Relevation v%s, (c) 2011-2014 Toni Corvera\n' % __version__) |
|
# ---------- OPTIONS ---------- # |
( datafile, password, mode ) = load_config() |
438,14 → 471,7 |
finally: |
if f: |
f.close() |
# Pad password |
password += (chr(0) * (32 - len(password))) |
# Decrypt. Decrypted data is compressed |
cleardata_gz = decrypt_gz(password, data) |
# Length of data padding |
padlen = ord(cleardata_gz[-1]) |
# Decompress actual data (15 is wbits [ref3] DON'T CHANGE, 2**15 is the (initial) buf size) |
xmldata = zlib.decompress(cleardata_gz[:-padlen], 15, 2**15) |
xmldata = DataReader(datafile, data).get_xml(password) |
|
# ---------- QUERIES ---------- # |
if dump_xml: |