sshwot/src/read_file.py

68 lines
1.7 KiB
Python

import entry
class FileFormatError(Exception): pass
class VersionMismatch(Exception): pass
def check_header(f):
"""check_header(file(rb))
Throw an error if the header isn't good"""
# Magic is b'WOT'
magic = f.read(3)
if magic != b'WOT':
raise FileFormatError('Invalid magic')
# Version 0 is the current one
version = f.read(1)
if version == b'':
raise FileFormatError('Unexpected end of file')
if version != b'\0':
raise VersionMismatch('Version %i not supported' % version[0])
def read_entry(f):
"""read_entry(file(rb)) → Entry / None
Returns None if the end of file has been reached"""
# u8[32]: salt
salt = f.read(32)
if len(salt) == 0:
# End of file has been reached, return None to mark that
return None
elif len(salt) != 32:
raise FileFormatError('Unexpected end of file')
# u8[32]: hashed_host
hashed_host = f.read(32)
if len(hashed_host) != 32:
raise FileFormatError('Unexpected end of file')
# u8[32]: fingerprint
fingerprint = f.read(32)
if len(fingerprint) != 32:
raise FileFormatError('Unexpected end of file')
# u16le: comment_length
length_bytes = f.read(2)
if len(length_bytes) != 2:
raise FileFormatError('Unexpected end of file')
comment_length = length_bytes[0] | length_bytes[1] << 8
# u8[comment_length]: comment
comment = f.read(comment_length)
if len(comment) != comment_length:
raise FileFormatError('Unexpected end of file')
return entry.Entry(salt, hashed_host, fingerprint, comment)
def read(f):
"""read_file(file(rb)) → [Entry]"""
check_header(f)
entries = []
while True:
# Read until we reach the end of file
entry = read_entry(f)
if entry is None: break
entries.append(entry)
return entries