libkeepass / pykeepass

Python library to interact with keepass databases (supports KDBX3 and KDBX4)
https://pypi.org/project/pykeepass/
GNU General Public License v3.0
411 stars 96 forks source link

How do I search for expired entries? #307

Closed rtl19 closed 2 years ago

rtl19 commented 2 years ago

Looking at the documentation for the find_entries method, I don't see a way to find any entries that are expired. Am I missing something?

Also, is there a method that indicates if an entry is expired or not? I've taking to coding something but I don't know if I'm leaving out any data points in my approach. Basically, I'm doing something like: if myentry.expires and myentry.expiry_time >= datetime.now(): isexpired=True else: isexpired=False

Evidlo commented 2 years ago

That might be hard to do properly via XPath expressions, which is how find_entries works under the hood. KeePass 4 databases base64 encode entry expiry times as seconds since 0001-01-01. We'd have to write an XPath expression to compare these base64 strings to b64encode(current_secs_since_0001_01_01), which I think is not possible since base64 doesn't preserve order.

>>> from base64 import b64encode
>>> b64encode(b'125') > b64encode(b'124')
True
>>> b64encode(b'124') > b64encode(b'123')
False

https://stackoverflow.com/questions/53301280/does-base64-encoding-preserve-alphabetical-ordering

rtl19 commented 2 years ago

That might be hard to do properly via XPath expressions, which is how find_entries works under the hood. KeePass 4 databases base64 encode entry expiry times as seconds since 0001-01-01. We'd have to write an XPath expression to compare these base64 strings to b64encode(current_secs_since_0001_01_01), which I think is not possible since base64 doesn't preserve order.

>>> from base64 import b64encode
>>> b64encode(b'125') > b64encode(b'124')
True
>>> b64encode(b'124') > b64encode(b'123')
False

https://stackoverflow.com/questions/53301280/does-base64-encoding-preserve-alphabetical-ordering

Just wondering, don't the entries have to be decoded anyway for them to be in the keepass.entries (the flattened entries of the entire database)? Is it fair to assume I can write my own search that loops thru these entries?

Can you create a method that returns True/False if an entry is expired? If not, is this the right logic to determine if an entry is expired:

if myentry.expires and myentry.expiry_time >= datetime.now(): 
    isexpired=True 
else: 
    isexpired=False
Evidlo commented 2 years ago

There is already entry.expired. I will document it in the README.