Skip to content

Commit ac2653a

Browse files
committed
Fix composite key computation for BytesIO
In case a keyfile as BytesIO has been read before, the next read will be empty. We need to ensure that we are reading the data from the beginning. Add seek to start to fix it.
1 parent e43ca6c commit ac2653a

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

pykeepass/kdbx_parsing/common.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import base64
22
import codecs
33
import hashlib
4+
import io
45
import logging
56
import re
67
import zlib
78
from binascii import Error as BinasciiError
89
from collections import OrderedDict
910
from copy import deepcopy
10-
from io import BytesIO
1111

1212
from construct import (
1313
Adapter,
@@ -128,6 +128,8 @@ def compute_key_composite(password=None, keyfile=None):
128128
# hash the keyfile
129129
if keyfile:
130130
if hasattr(keyfile, "read"):
131+
if hasattr(keyfile, "seekable") and keyfile.seekable():
132+
keyfile.seek(0)
131133
keyfile_bytes = keyfile.read()
132134
else:
133135
with open(keyfile, 'rb') as f:
@@ -194,7 +196,7 @@ class XML(Adapter):
194196

195197
def _decode(self, data, con, path):
196198
parser = etree.XMLParser(remove_blank_text=True)
197-
return etree.parse(BytesIO(data), parser)
199+
return etree.parse(io.BytesIO(data), parser)
198200

199201
def _encode(self, tree, con, path):
200202
return etree.tostring(tree)

tests/tests.py

+14
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,20 @@ def test_fields(self):
875875

876876

877877
class PyKeePassTests3(KDBX3Tests):
878+
def test_consecutives_saves_with_stream(self):
879+
# https://github.com/libkeepass/pykeepass/pull/388
880+
self.setUp()
881+
882+
with open(base_dir / self.keyfile_tmp, 'rb') as f:
883+
keyfile = BytesIO(f.read())
884+
885+
for _i in range(5):
886+
with PyKeePass(
887+
base_dir / self.database_tmp,
888+
password=self.password,
889+
keyfile=keyfile,
890+
) as kp:
891+
kp.save()
878892

879893
def test_set_credentials(self):
880894
self.kp_tmp.password = 'f00bar'

0 commit comments

Comments
 (0)