Skip to content

Commit e2db857

Browse files
committed
- allow raw 32 byte keys in FernetEncrypter (bypass PBKDF2HMAC)
- allow no key (generate random key)
1 parent 6a3adab commit e2db857

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed

src/cryptojwt/jwe/fernet.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
class FernetEncrypter(Encrypter):
1717
def __init__(
1818
self,
19-
password: str,
19+
password: Optional[str] = None,
20+
key: Optional[bytes] = None,
2021
salt: Optional[bytes] = "",
2122
hash_alg: Optional[str] = "SHA256",
2223
digest_size: Optional[int] = 0,
@@ -28,14 +29,22 @@ def __init__(
2829
else:
2930
salt = as_bytes(salt)
3031

31-
_alg = getattr(hashes, hash_alg)
32-
# A bit special for SHAKE* and BLAKE* hashes
33-
if hash_alg.startswith("SHAKE") or hash_alg.startswith("BLAKE"):
34-
_algorithm = _alg(digest_size)
32+
if password is not None:
33+
_alg = getattr(hashes, hash_alg)
34+
# A bit special for SHAKE* and BLAKE* hashes
35+
if hash_alg.startswith("SHAKE") or hash_alg.startswith("BLAKE"):
36+
_algorithm = _alg(digest_size)
37+
else:
38+
_algorithm = _alg()
39+
kdf = PBKDF2HMAC(algorithm=_algorithm, length=32, salt=salt, iterations=iterations)
40+
self.key = base64.urlsafe_b64encode(kdf.derive(as_bytes(password)))
41+
elif key is not None:
42+
if len(key) != 32:
43+
raise ValueError("Raw key must be 32 bytes")
44+
self.key = base64.urlsafe_b64encode(as_bytes(key))
3545
else:
36-
_algorithm = _alg()
37-
kdf = PBKDF2HMAC(algorithm=_algorithm, length=32, salt=salt, iterations=iterations)
38-
self.key = base64.urlsafe_b64encode(kdf.derive(as_bytes(password)))
46+
self.key = Fernet.generate_key()
47+
3948
self.core = Fernet(self.key)
4049

4150
def encrypt(self, msg: Union[str, bytes], **kwargs) -> bytes:

tests/test_07_jwe.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,39 @@ def test_invalid():
648648
decrypter.decrypt("a.b.c.d.e", keys=[encryption_key])
649649

650650

651-
def test_fernet():
651+
def test_fernet_password():
652+
encrypter = FernetEncrypter(password="DukeofHazardpass")
653+
_token = encrypter.encrypt(plain)
654+
655+
decrypter = encrypter
656+
resp = decrypter.decrypt(_token)
657+
assert resp == plain
658+
659+
660+
def test_fernet_symkey():
652661
encryption_key = SYMKey(use="enc", key="DukeofHazardpass", kid="some-key-id")
653662

654-
encrypter = FernetEncrypter(encryption_key.key)
663+
encrypter = FernetEncrypter(password=encryption_key.key)
664+
_token = encrypter.encrypt(plain)
665+
666+
decrypter = encrypter
667+
resp = decrypter.decrypt(_token)
668+
assert resp == plain
669+
670+
671+
def test_fernet_bytes():
672+
key = os.urandom(32)
673+
674+
encrypter = FernetEncrypter(key=key)
675+
_token = encrypter.encrypt(plain)
676+
677+
decrypter = encrypter
678+
resp = decrypter.decrypt(_token)
679+
assert resp == plain
680+
681+
682+
def test_fernet_default_key():
683+
encrypter = FernetEncrypter()
655684
_token = encrypter.encrypt(plain)
656685

657686
decrypter = encrypter
@@ -662,7 +691,7 @@ def test_fernet():
662691
def test_fernet_sha512():
663692
encryption_key = SYMKey(use="enc", key="DukeofHazardpass", kid="some-key-id")
664693

665-
encrypter = FernetEncrypter(encryption_key.key, hash_alg="SHA512")
694+
encrypter = FernetEncrypter(password=encryption_key.key, hash_alg="SHA512")
666695
_token = encrypter.encrypt(plain)
667696

668697
decrypter = encrypter
@@ -674,7 +703,7 @@ def test_fernet_blake2s():
674703
encryption_key = SYMKey(use="enc", key="DukeofHazardpass", kid="some-key-id")
675704

676705
encrypter = FernetEncrypter(
677-
encryption_key.key, hash_alg="BLAKE2s", digest_size=32, iterations=1000
706+
password=encryption_key.key, hash_alg="BLAKE2s", digest_size=32, iterations=1000
678707
)
679708
_token = encrypter.encrypt(plain)
680709

0 commit comments

Comments
 (0)