Skip to content

Commit f131e50

Browse files
author
Fabien Coelho
committed
reorder classes and functions more logically
1 parent e2c7f14 commit f131e50

File tree

1 file changed

+86
-84
lines changed

1 file changed

+86
-84
lines changed

CacheToolsUtils.py

+86-84
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,92 @@ def reset(self): # pragma: no cover
367367
self._cache2.reset() # type: ignore
368368

369369

370+
#
371+
# Encrypted Cache
372+
#
373+
class EncryptedCache(_KeyMutMapMix, _StatsMix, MutableMapping):
374+
"""Encrypted Bytes Key-Value Cache.
375+
376+
:param secret: bytes of secret, at least 16 bytes.
377+
:param hsize: size of hashed key, default is 16.
378+
379+
The key is *not* encrypted but simply hashed, thus they are
380+
fixed size with a very low collision probability.
381+
382+
By design, the clear-text key is needed to recover the value,
383+
as each value is encrypted with its own key.
384+
385+
There is no integrity check on the value.
386+
387+
Algorithms:
388+
- SHA3: hash/key/nonce derivation.
389+
- Salsa20: value encryption.
390+
"""
391+
392+
def __init__(self, cache: MutableMapping, secret: bytes, hsize: int = 16):
393+
self._cache = cache
394+
assert len(secret) >= 16
395+
self._secret = secret
396+
assert 8 <= hsize <= 24
397+
self._hsize = hsize
398+
from Crypto.Cipher import Salsa20
399+
self._cipher = Salsa20
400+
401+
def _keydev(self, key):
402+
hkey = hashlib.sha3_512(key + self._secret).digest()
403+
sz = self._hsize
404+
return (hkey[:sz], hkey[sz:sz+32], hkey[sz+32:sz+40])
405+
406+
def _key(self, key):
407+
return self._keydev(key)[0]
408+
409+
def __setitem__(self, key, val):
410+
hkey, vkey, vnonce = self._keydev(key)
411+
self._cache[hkey] = self._cipher.new(key=vkey, nonce=vnonce).encrypt(val)
412+
413+
def __getitem__(self, key):
414+
hkey, vkey, vnonce = self._keydev(key)
415+
return self._cipher.new(key=vkey, nonce=vnonce).decrypt(self._cache[hkey])
416+
417+
418+
class BytesCache(_KeyMutMapMix, _StatsMix, MutableMapping):
419+
"""Map bytes to strings."""
420+
421+
def __init__(self, cache):
422+
self._cache = cache
423+
424+
def _key(self, key):
425+
# assert isinstance(key, bytes)
426+
return base64.b85encode(key).decode("ASCII")
427+
428+
def __setitem__(self, key, val):
429+
self._cache.__setitem__(self._key(key), self._key(val))
430+
431+
def __getitem__(self, key):
432+
val = self._cache.__getitem__(self._key(key))
433+
# assert isinstance(val, str)
434+
return base64.b85decode(val)
435+
436+
437+
class ToBytesCache(_KeyMutMapMix, _StatsMix, MutableMapping):
438+
"""Map (JSON-serializable) cache keys and values to bytes."""
439+
440+
def __init__(self, cache):
441+
self._cache = cache
442+
443+
def _key(self, key):
444+
return json.dumps(key, sort_keys=True, separators=(",", ":")).encode("UTF-8")
445+
446+
def __setitem__(self, key, val):
447+
self._cache.__setitem__(self._key(key), self._key(val))
448+
449+
def __getitem__(self, key):
450+
return json.loads(self._cache.__getitem__(self._key(key)).decode("UTF-8"))
451+
452+
453+
#
454+
# CACHED DECORATOR AND HELPERS
455+
#
370456
def cached(cache, *args, **kwargs):
371457
"""Extended decorator with delete and exists.
372458
@@ -508,93 +594,9 @@ def full_hash_key(*args, **kwargs) -> str:
508594
return base64.b85encode(hkey).decode("ASCII")
509595

510596

511-
#
512-
# Encrypted Cache
513-
#
514-
class EncryptedCache(_KeyMutMapMix, _StatsMix, MutableMapping):
515-
"""Encrypted Bytes Key-Value Cache.
516-
517-
:param secret: bytes of secret, at least 16 bytes.
518-
:param hsize: size of hashed key, default is 16.
519-
520-
The key is *not* encrypted but simply hashed, thus they are
521-
fixed size with a very low collision probability.
522-
523-
By design, the clear-text key is needed to recover the value,
524-
as each value is encrypted with its own key.
525-
526-
There is no integrity check on the value.
527-
528-
Algorithms:
529-
- SHA3: hash/key/nonce derivation.
530-
- Salsa20: value encryption.
531-
"""
532-
533-
def __init__(self, cache: MutableMapping, secret: bytes, hsize: int = 16):
534-
self._cache = cache
535-
assert len(secret) >= 16
536-
self._secret = secret
537-
assert 8 <= hsize <= 24
538-
self._hsize = hsize
539-
from Crypto.Cipher import Salsa20
540-
self._cipher = Salsa20
541-
542-
def _keydev(self, key):
543-
hkey = hashlib.sha3_512(key + self._secret).digest()
544-
sz = self._hsize
545-
return (hkey[:sz], hkey[sz:sz+32], hkey[sz+32:sz+40])
546-
547-
def _key(self, key):
548-
return self._keydev(key)[0]
549-
550-
def __setitem__(self, key, val):
551-
hkey, vkey, vnonce = self._keydev(key)
552-
self._cache[hkey] = self._cipher.new(key=vkey, nonce=vnonce).encrypt(val)
553-
554-
def __getitem__(self, key):
555-
hkey, vkey, vnonce = self._keydev(key)
556-
return self._cipher.new(key=vkey, nonce=vnonce).decrypt(self._cache[hkey])
557-
558-
559-
class BytesCache(_KeyMutMapMix, _StatsMix, MutableMapping):
560-
"""Map bytes to strings."""
561-
562-
def __init__(self, cache):
563-
self._cache = cache
564-
565-
def _key(self, key):
566-
# assert isinstance(key, bytes)
567-
return base64.b85encode(key).decode("ASCII")
568-
569-
def __setitem__(self, key, val):
570-
self._cache.__setitem__(self._key(key), self._key(val))
571-
572-
def __getitem__(self, key):
573-
val = self._cache.__getitem__(self._key(key))
574-
# assert isinstance(val, str)
575-
return base64.b85decode(val)
576-
577-
578-
class ToBytesCache(_KeyMutMapMix, _StatsMix, MutableMapping):
579-
"""Map (JSON-serializable) cache keys and values to bytes."""
580-
581-
def __init__(self, cache):
582-
self._cache = cache
583-
584-
def _key(self, key):
585-
return json.dumps(key, sort_keys=True, separators=(",", ":")).encode("UTF-8")
586-
587-
def __setitem__(self, key, val):
588-
self._cache.__setitem__(self._key(key), self._key(val))
589-
590-
def __getitem__(self, key):
591-
return json.loads(self._cache.__getitem__(self._key(key)).decode("UTF-8"))
592-
593-
594597
#
595598
# MEMCACHED
596599
#
597-
# FIXME what about bytes?
598600
class JsonSerde:
599601
"""JSON serialize/deserialize class for MemCached (``pymemcache``).
600602

0 commit comments

Comments
 (0)