diff --git a/docs/examples/umbral_simple_api.py b/docs/examples/umbral_simple_api.py index 22e1030f..e28d3802 100644 --- a/docs/examples/umbral_simple_api.py +++ b/docs/examples/umbral_simple_api.py @@ -1,8 +1,7 @@ import random from umbral import ( - SecretKey, PublicKey, + SecretKey, PublicKey, GenericError, encrypt, generate_kfrags, reencrypt, decrypt_original, decrypt_reencrypted) -from umbral.dem import ErrorInvalidTag # Generate an Umbral key pair # --------------------------- @@ -46,7 +45,7 @@ # Attempt Bob's decryption (fail) try: fail_decrypted_data = decrypt_original(bobs_secret_key, bob_capsule, ciphertext) -except ErrorInvalidTag: +except GenericError: print("Decryption failed! Bob doesn't has access granted yet.") # Alice grants access to Bob by generating kfrags diff --git a/docs/notebooks/pyUmbral Simple API.ipynb b/docs/notebooks/pyUmbral Simple API.ipynb index 5ac9da0c..6962723c 100644 --- a/docs/notebooks/pyUmbral Simple API.ipynb +++ b/docs/notebooks/pyUmbral Simple API.ipynb @@ -140,13 +140,13 @@ } ], "source": [ - "from umbral.dem import ErrorInvalidTag\n", + "from umbral import GenericError\n", "\n", "try:\n", " fail_decrypted_data = decrypt_original(sk=bobs_private_key,\n", " capsule=capsule,\n", " ciphertext=ciphertext)\n", - "except ErrorInvalidTag:\n", + "except GenericError:\n", " print(\"Decryption failed! Bob doesn't has access granted yet.\")\n" ] }, diff --git a/docs/source/api.rst b/docs/source/api.rst index 27e691b4..de61bfdd 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -52,6 +52,9 @@ Encryption, re-encryption and decryption Utilities --------- +.. autoclass:: umbral.GenericError + :show-inheritance: + .. autoclass:: umbral.serializable.Serializable :members: from_bytes :special-members: __bytes__ diff --git a/docs/source/using_pyumbral.rst b/docs/source/using_pyumbral.rst index 56f6c15f..396f9f15 100644 --- a/docs/source/using_pyumbral.rst +++ b/docs/source/using_pyumbral.rst @@ -134,7 +134,7 @@ or re-encrypted for him by Ursula, he will not be able to open it. ... ciphertext=ciphertext) Traceback (most recent call last): ... - umbral.dem.ErrorInvalidTag + umbral.GenericError Ursulas perform re-encryption diff --git a/tests/test_capsule.py b/tests/test_capsule.py index 5786f38c..46a09ffb 100644 --- a/tests/test_capsule.py +++ b/tests/test_capsule.py @@ -4,6 +4,7 @@ Capsule, SecretKey, PublicKey, + GenericError, encrypt, decrypt_original, reencrypt, @@ -27,7 +28,7 @@ def test_capsule_serialization(alices_keys): capsule.point_e = CurvePoint.random() capsule_bytes = bytes(capsule) - with pytest.raises(Capsule.NotValid): + with pytest.raises(GenericError): Capsule.from_bytes(capsule_bytes) @@ -84,7 +85,7 @@ def test_open_reencrypted(alices_keys, bobs_keys): capsule.open_reencrypted(receiving_sk, delegating_pk, []) # Not enough cfrags - with pytest.raises(ValueError, match="Internal validation failed"): + with pytest.raises(GenericError, match="Internal validation failed"): capsule.open_reencrypted(receiving_sk, delegating_pk, cfrags[:threshold-1]) # Repeating cfrags diff --git a/tests/test_dem.py b/tests/test_dem.py index d0e6c9a9..7d5a5b12 100644 --- a/tests/test_dem.py +++ b/tests/test_dem.py @@ -1,7 +1,8 @@ import pytest import os -from umbral.dem import DEM, ErrorInvalidTag +from umbral import GenericError +from umbral.dem import DEM def test_encrypt_decrypt(): @@ -47,7 +48,7 @@ def test_malformed_ciphertext(): dem.decrypt(ciphertext[:DEM.NONCE_SIZE + DEM.TAG_SIZE - 1]) # Too long - with pytest.raises(ErrorInvalidTag): + with pytest.raises(GenericError): dem.decrypt(ciphertext + b'abcd') @@ -76,5 +77,5 @@ def test_encrypt_decrypt_associated_data(): assert cleartext1 == plaintext # Attempt decryption with invalid associated data - with pytest.raises(ErrorInvalidTag): + with pytest.raises(GenericError): cleartext2 = dem.decrypt(ciphertext0, authenticated_data=b'wrong data') diff --git a/tests/test_pre.py b/tests/test_pre.py index 0ee5b7a4..94617ebe 100644 --- a/tests/test_pre.py +++ b/tests/test_pre.py @@ -3,13 +3,13 @@ from umbral import ( SecretKey, PublicKey, + GenericError, encrypt, generate_kfrags, decrypt_original, reencrypt, decrypt_reencrypted, ) -from umbral.dem import ErrorInvalidTag def test_public_key_encryption(alices_keys): @@ -22,7 +22,7 @@ def test_public_key_encryption(alices_keys): # Wrong secret key sk = SecretKey.random() - with pytest.raises(ErrorInvalidTag): + with pytest.raises(GenericError): decrypt_original(sk, capsule, ciphertext) diff --git a/umbral/__init__.py b/umbral/__init__.py index 130758f0..38c55f4c 100644 --- a/umbral/__init__.py +++ b/umbral/__init__.py @@ -4,6 +4,7 @@ from .capsule import Capsule from .capsule_frag import CapsuleFrag +from .errors import GenericError from .key_frag import KeyFrag, generate_kfrags from .keys import SecretKey, PublicKey, SecretKeyFactory from .pre import encrypt, decrypt_original, decrypt_reencrypted, reencrypt @@ -23,6 +24,7 @@ "Capsule", "KeyFrag", "CapsuleFrag", + "GenericError", "encrypt", "decrypt_original", "generate_kfrags", diff --git a/umbral/capsule.py b/umbral/capsule.py index 68add3cb..a455eaea 100644 --- a/umbral/capsule.py +++ b/umbral/capsule.py @@ -2,6 +2,7 @@ from .curve_point import CurvePoint from .curve_scalar import CurveScalar +from .errors import GenericError from .hashing import hash_capsule_points, hash_to_polynomial_arg, hash_to_shared_secret from .keys import PublicKey, SecretKey from .params import PARAMETERS @@ -24,11 +25,6 @@ class Capsule(Serializable): Encapsulated symmetric key. """ - class NotValid(ValueError): - """ - raised if the capsule does not pass verification. - """ - def __init__(self, point_e: CurvePoint, point_v: CurvePoint, signature: CurveScalar): self.point_e = point_e self.point_v = point_v @@ -40,7 +36,7 @@ def __take__(cls, data: bytes) -> Tuple['Capsule', bytes]: capsule = cls(e, v, sig) if not capsule._verify(): - raise cls.NotValid("Capsule verification failed.") + raise GenericError("Capsule self-verification failed. Serialized data may be damaged.") return capsule, data @@ -111,7 +107,7 @@ def open_reencrypted(self, # TODO: check for d == 0? Or just let if fail? inv_d = d.invert() if orig_pub_key * (s * inv_d) != (e_prime * h) + v_prime: - raise ValueError("Internal validation failed") + raise GenericError("Internal validation failed") return (e_prime + v_prime) * d diff --git a/umbral/dem.py b/umbral/dem.py index b23fe9ba..042a1ee7 100644 --- a/umbral/dem.py +++ b/umbral/dem.py @@ -14,6 +14,7 @@ ) from . import openssl +from .errors import GenericError def kdf(data: bytes, @@ -30,10 +31,6 @@ def kdf(data: bytes, return hkdf.derive(data) -class ErrorInvalidTag(Exception): - pass - - class DEM: KEY_SIZE = XCHACHA_KEY_SIZE @@ -67,4 +64,6 @@ def decrypt(self, nonce_and_ciphertext: bytes, authenticated_data: bytes = b"") try: return xchacha_decrypt(ciphertext, authenticated_data, nonce, self._key) except nacl.exceptions.CryptoError: - raise ErrorInvalidTag + raise GenericError("Decryption of ciphertext failed: " + "either someone tampered with the ciphertext or " + "you are using an incorrect decryption key.") diff --git a/umbral/errors.py b/umbral/errors.py new file mode 100644 index 00000000..328c3b9f --- /dev/null +++ b/umbral/errors.py @@ -0,0 +1,5 @@ +class GenericError(Exception): + """ + An interal Umbral error, see the message for details. + """ + pass