From c99a1f53dfff1f48191c0794fc71d46bb6b052f8 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 15 Jan 2020 11:20:48 +0100 Subject: [PATCH] Switch from md5 to sha256 for UIDs and tokens --- config | 3 ++- radicale/item/__init__.py | 4 ++-- radicale/storage/__init__.py | 4 ++-- radicale/storage/multifilesystem/cache.py | 4 ++-- radicale/storage/multifilesystem/sync.py | 10 +++++----- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/config b/config index 02f9237..45c768a 100644 --- a/config +++ b/config @@ -70,7 +70,8 @@ # Htpasswd encryption method # Value: plain | sha1 | ssha | crypt | bcrypt | md5 # Only bcrypt can be considered secure. -# bcrypt and md5 require the passlib library to be installed. +# bcrypt requires the passlib[bcrypt] module and md5 requires +# the passlib module. #htpasswd_encryption = bcrypt # Incorrect authentication delay (seconds) diff --git a/radicale/item/__init__.py b/radicale/item/__init__.py index cdda525..d4ff3bb 100644 --- a/radicale/item/__init__.py +++ b/radicale/item/__init__.py @@ -25,7 +25,7 @@ Module for address books and calendar entries (see ``Item``). import math import sys -from hashlib import md5 +from hashlib import sha256 from random import getrandbits import vobject @@ -183,7 +183,7 @@ def get_etag(text): Encoded as quoted-string (see RFC 2616). """ - etag = md5() + etag = sha256() etag.update(text.encode("utf-8")) return '"%s"' % etag.hexdigest() diff --git a/radicale/storage/__init__.py b/radicale/storage/__init__.py index 7526d3d..b214587 100644 --- a/radicale/storage/__init__.py +++ b/radicale/storage/__init__.py @@ -25,7 +25,7 @@ Take a look at the class ``BaseCollection`` if you want to implement your own. import contextlib import json -from hashlib import md5 +from hashlib import sha256 import pkg_resources import vobject @@ -79,7 +79,7 @@ class BaseCollection: @property def etag(self): """Encoded as quoted-string (see RFC 2616).""" - etag = md5() + etag = sha256() for item in self.get_all(): etag.update((item.href + "/" + item.etag).encode("utf-8")) etag.update(json.dumps(self.get_meta(), sort_keys=True).encode()) diff --git a/radicale/storage/multifilesystem/cache.py b/radicale/storage/multifilesystem/cache.py index 56812ed..e1a087c 100644 --- a/radicale/storage/multifilesystem/cache.py +++ b/radicale/storage/multifilesystem/cache.py @@ -19,7 +19,7 @@ import os import pickle import time -from hashlib import md5 +from hashlib import sha256 from radicale import pathutils, storage from radicale.log import logger @@ -54,7 +54,7 @@ class CollectionCacheMixin: self._storage._sync_directory(folder) def _item_cache_hash(self, raw_text): - _hash = md5() + _hash = sha256() _hash.update(storage.CACHE_VERSION) _hash.update(raw_text) return _hash.hexdigest() diff --git a/radicale/storage/multifilesystem/sync.py b/radicale/storage/multifilesystem/sync.py index 68e0384..d1ffcb1 100644 --- a/radicale/storage/multifilesystem/sync.py +++ b/radicale/storage/multifilesystem/sync.py @@ -19,7 +19,7 @@ import itertools import os import pickle -from hashlib import md5 +from hashlib import sha256 from radicale.log import logger @@ -27,10 +27,10 @@ from radicale.log import logger class CollectionSyncMixin: def sync(self, old_token=None): # The sync token has the form http://radicale.org/ns/sync/TOKEN_NAME - # where TOKEN_NAME is the md5 hash of all history etags of present and - # past items of the collection. + # where TOKEN_NAME is the sha256 hash of all history etags of present + # and past items of the collection. def check_token_name(token_name): - if len(token_name) != 32: + if len(token_name) != 64: return False for c in token_name: if c not in "0123456789abcdef": @@ -47,7 +47,7 @@ class CollectionSyncMixin: raise ValueError("Malformed token: %r" % old_token) # Get the current state and sync-token of the collection. state = {} - token_name_hash = md5() + token_name_hash = sha256() # Find the history of all existing and deleted items for href, item in itertools.chain( ((item.href, item) for item in self.get_all()),