From a887fa2065b396ebdf3e768305bf63bef8f79dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Borgstr=C3=B6m?= Date: Fri, 5 Jul 2013 16:57:36 +0200 Subject: [PATCH] Verify hash before decompressing with PlaintextKey --- darc/key.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/darc/key.py b/darc/key.py index 35aa2990d..490eef4cd 100644 --- a/darc/key.py +++ b/darc/key.py @@ -12,10 +12,6 @@ from .helpers import IntegrityError, get_keys_dir PREFIX = b'\0' * 8 -KEYFILE = b'\0' -PASSPHRASE = b'\1' -PLAINTEXT = b'\2' - class HMAC(hmac.HMAC): @@ -33,11 +29,11 @@ def key_creator(repository, args): def key_factory(repository, manifest_data): - if manifest_data[:1] == KEYFILE: + if manifest_data[0] == KeyfileKey.TYPE: return KeyfileKey.detect(repository, manifest_data) - elif manifest_data[:1] == PASSPHRASE: + elif manifest_data[0] == PassphraseKey.TYPE: return PassphraseKey.detect(repository, manifest_data) - elif manifest_data[:1] == PLAINTEXT: + elif manifest_data[0] == PlaintextKey.TYPE: return PlaintextKey.detect(repository, manifest_data) else: raise Exception('Unkown Key type %d' % ord(manifest_data[0])) @@ -45,6 +41,9 @@ def key_factory(repository, manifest_data): class KeyBase(object): + def __init__(self): + self.TYPE_STR = bytes([self.TYPE]) + def id_hash(self, data): """Return HMAC hash using the "id" HMAC key """ @@ -57,7 +56,7 @@ class KeyBase(object): class PlaintextKey(KeyBase): - TYPE = PLAINTEXT + TYPE = 0x02 chunk_seed = 0 @@ -74,12 +73,19 @@ class PlaintextKey(KeyBase): return sha256(data).digest() def encrypt(self, data): - return b''.join([self.TYPE, zlib.compress(data)]) + cdata = zlib.compress(data) + hash = sha256(cdata).digest() + return b''.join([self.TYPE_STR, hash, cdata]) def decrypt(self, id, data): - if data[:1] != self.TYPE: + if data[0] != self.TYPE: raise IntegrityError('Invalid encryption envelope') - data = zlib.decompress(memoryview(data)[1:]) + # This is just a hash and not a hmac but it will at least + # stop unintentionally corrupted data from hitting zlib.decompress() + hash = memoryview(data)[1:33] + if memoryview(sha256(memoryview(data)[33:]).digest()) != hash: + raise IntegrityError('Payload checksum mismatch') + data = zlib.decompress(memoryview(data)[33:]) if id and sha256(data).digest() != id: raise IntegrityError('Chunk id verification failed') return data @@ -96,14 +102,14 @@ class AESKeyBase(KeyBase): data = zlib.compress(data) self.enc_cipher.reset() data = b''.join((self.enc_cipher.iv[8:], self.enc_cipher.encrypt(data))) - hash = HMAC(self.enc_hmac_key, data, sha256).digest() - return b''.join((self.TYPE, hash, data)) + hmac = HMAC(self.enc_hmac_key, data, sha256).digest() + return b''.join((self.TYPE_STR, hmac, data)) def decrypt(self, id, data): - if data[:1] != self.TYPE: + if data[0] != self.TYPE: raise IntegrityError('Invalid encryption envelope') - hash = memoryview(data)[1:33] - if memoryview(HMAC(self.enc_hmac_key, memoryview(data)[33:], sha256).digest()) != hash: + hmac = memoryview(data)[1:33] + if memoryview(HMAC(self.enc_hmac_key, memoryview(data)[33:], sha256).digest()) != hmac: raise IntegrityError('Encryption envelope checksum mismatch') self.dec_cipher.reset(iv=PREFIX + data[33:41]) data = zlib.decompress(self.dec_cipher.decrypt(data[41:])) # should use memoryview @@ -112,7 +118,7 @@ class AESKeyBase(KeyBase): return data def extract_iv(self, payload): - if payload[:1] != self.TYPE: + if payload[0] != self.TYPE: raise IntegrityError('Invalid encryption envelope') nonce = bytes_to_long(payload[33:41]) return nonce @@ -132,7 +138,7 @@ class AESKeyBase(KeyBase): class PassphraseKey(AESKeyBase): - TYPE = PASSPHRASE + TYPE = 0x01 iterations = 100000 @classmethod @@ -179,7 +185,7 @@ class PassphraseKey(AESKeyBase): class KeyfileKey(AESKeyBase): FILE_ID = 'DARC KEY' - TYPE = KEYFILE + TYPE = 0x00 @classmethod def detect(cls, repository, manifest_data):