aabmets / quantcrypt

Cross-platform Python library for Post-Quantum Cryptography using precompiled PQClean binaries

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Kyber does not appear to work on Python 3.11.6, MacOS 14.3 on M1 Mac

jathanism opened this issue · comments

Using quantcrypt 0.3.3.

Was following the docs to play around and ran into this issue:

In [21]: from quantcrypt import (
    ...:     kem,     # Key Encapsulation Mechanism algos   - public-key cryptography
    ...:     dss,     # Digital Signature Scheme algos      - secret-key signatures
    ...:     cipher,  # The Krypton Cipher                  - symmetric cipher based on AES-256
    ...:     kdf,     # Argon2 helpers + KMAC-KDF           - key derivation functions
    ...:     errors,  # All errors QuantCrypt may raise     - also available from other modules
    ...:     utils    # Helper utilities from all modules   - gathered into one module
    ...: )

In [22]: k = kem.Kyber()
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/quantcrypt/internal/pqa/common.py:75, in BasePQAlgorithm.__init__(self, variant)
     74 _var = variant or PQAVariant.AVX2
---> 75 self._lib = self._import(_var)
     76 self.variant = _var

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/quantcrypt/internal/pqa/common.py:66, in BasePQAlgorithm._import(self, variant)
     64 @lru_cache
     65 def _import(self, variant: PQAVariant) -> ModuleType:
---> 66 	return importlib.import_module(
     67 		f"quantcrypt.internal.bin.{platform.system()}" +
     68 		f".{variant.value}.{self.name.replace('-', '_')}"
     69 	).lib

File ~/.pyenv/versions/3.11.6/lib/python3.11/importlib/__init__.py:126, in import_module(name, package)
    125         level += 1
--> 126 return _bootstrap._gcd_import(name[level:], package, level)

File <frozen importlib._bootstrap>:1204, in _gcd_import(name, package, level)

File <frozen importlib._bootstrap>:1176, in _find_and_load(name, import_)

File <frozen importlib._bootstrap>:1126, in _find_and_load_unlocked(name, import_)

File <frozen importlib._bootstrap>:241, in _call_with_frames_removed(f, *args, **kwds)

File <frozen importlib._bootstrap>:1204, in _gcd_import(name, package, level)

File <frozen importlib._bootstrap>:1176, in _find_and_load(name, import_)

File <frozen importlib._bootstrap>:1140, in _find_and_load_unlocked(name, import_)

ModuleNotFoundError: No module named 'quantcrypt.internal.bin.Darwin.avx2'

During handling of the above exception, another exception occurred:

SystemExit                                Traceback (most recent call last)
    [... skipping hidden 1 frame]

Cell In[22], line 1
----> 1 k = kem.Kyber()

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/pydantic/validate_call_decorator.py:58, in validate_call.<locals>.validate.<locals>.wrapper_function(*args, **kwargs)
     56 @functools.wraps(function)
     57 def wrapper_function(*args, **kwargs):
---> 58     return validate_call_wrapper(*args, **kwargs)

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/pydantic/_internal/_validate_call.py:81, in ValidateCallWrapper.__call__(self, *args, **kwargs)
     80 def __call__(self, *args: Any, **kwargs: Any) -> Any:
---> 81     res = self.__pydantic_validator__.validate_python(pydantic_core.ArgsKwargs(args, kwargs))
     82     if self.__return_pydantic_validator__:

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/quantcrypt/internal/pqa/kem.py:144, in Kyber.__init__(self, variant)
    127 """
    128 Initializes the Kyber instance with C extension binaries.
    129 User is able to override which underlying binary is used for the
   (...)
    142 	should have CLEAN binaries available.
    143 """
--> 144 super().__init__(variant)

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/quantcrypt/internal/pqa/common.py:87, in BasePQAlgorithm.__init__(self, variant)
     86 	raise ex
---> 87 raise SystemExit(  # pragma: no cover
     88 	"Quantcrypt Fatal Error:\n"
     89 	"Unable to continue due to missing CLEAN binaries."
     90 )

SystemExit: Quantcrypt Fatal Error:
Unable to continue due to missing CLEAN binaries.

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
    [... skipping hidden 1 frame]

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/interactiveshell.py:2121, in InteractiveShell.showtraceback(self, exc_tuple, filename, tb_offset, exception_only, running_compiled_code)
   2118 if exception_only:
   2119     stb = ['An exception has occurred, use %tb to see '
   2120            'the full traceback.\n']
-> 2121     stb.extend(self.InteractiveTB.get_exception_only(etype,
   2122                                                      value))
   2123 else:
   2125     def contains_exceptiongroup(val):

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:710, in ListTB.get_exception_only(self, etype, value)
    702 def get_exception_only(self, etype, value):
    703     """Only print the exception type and message, without a traceback.
    704
    705     Parameters
   (...)
    708     value : exception value
    709     """
--> 710     return ListTB.structured_traceback(self, etype, value)

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:568, in ListTB.structured_traceback(self, etype, evalue, etb, tb_offset, context)
    565     chained_exc_ids.add(id(exception[1]))
    566     chained_exceptions_tb_offset = 0
    567     out_list = (
--> 568         self.structured_traceback(
    569             etype,
    570             evalue,
    571             (etb, chained_exc_ids),  # type: ignore
    572             chained_exceptions_tb_offset,
    573             context,
    574         )
    575         + chained_exception_message
    576         + out_list)
    578 return out_list

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:1435, in AutoFormattedTB.structured_traceback(self, etype, evalue, etb, tb_offset, number_of_lines_of_context)
   1433 else:
   1434     self.tb = etb
-> 1435 return FormattedTB.structured_traceback(
   1436     self, etype, evalue, etb, tb_offset, number_of_lines_of_context
   1437 )

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:1326, in FormattedTB.structured_traceback(self, etype, value, tb, tb_offset, number_of_lines_of_context)
   1323 mode = self.mode
   1324 if mode in self.verbose_modes:
   1325     # Verbose modes need a full traceback
-> 1326     return VerboseTB.structured_traceback(
   1327         self, etype, value, tb, tb_offset, number_of_lines_of_context
   1328     )
   1329 elif mode == 'Minimal':
   1330     return ListTB.get_exception_only(self, etype, value)

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:1173, in VerboseTB.structured_traceback(self, etype, evalue, etb, tb_offset, number_of_lines_of_context)
   1164 def structured_traceback(
   1165     self,
   1166     etype: type,
   (...)
   1170     number_of_lines_of_context: int = 5,
   1171 ):
   1172     """Return a nice text document describing the traceback."""
-> 1173     formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
   1174                                                            tb_offset)
   1176     colors = self.Colors  # just a shorthand + quicker name lookup
   1177     colorsnormal = colors.Normal  # used a lot

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:1063, in VerboseTB.format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset)
   1060 assert isinstance(tb_offset, int)
   1061 head = self.prepare_header(str(etype), self.long_header)
   1062 records = (
-> 1063     self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []
   1064 )
   1066 frames = []
   1067 skipped = 0

File ~/Library/Caches/pypoetry/virtualenvs/bi-sdk-eiGFesGp-py3.11/lib/python3.11/site-packages/IPython/core/ultratb.py:1131, in VerboseTB.get_records(self, etb, number_of_lines_of_context, tb_offset)
   1129 while cf is not None:
   1130     try:
-> 1131         mod = inspect.getmodule(cf.tb_frame)
   1132         if mod is not None:
   1133             mod_name = mod.__name__

AttributeError: 'tuple' object has no attribute 'tb_frame'

In [23]:

@jathanism
Hey, thank you for trying out QuantCrypt! Your avatar image sure scared me at first! :P

The issue you're encountering stems from the fact that prior to library version 0.3.4, the binaries built by GitHub actions used Python 3.10, which meant that the compiled binaries were only compatible with Python 3.10 (see closed issue #1).

At that time, I was not aware that CFFI compiled version-specific binaries. The latest version of QuantCrypt compiles the binaries with Python 3.12 and the library is marked to support only Python 3.12. This constriction ensures that when you install the library, the binaries are guaranteed to work with the version of Python that you are using. It would be possible to support multiple Python versions simultaneously, but this would require multiplying the package size by the size of the additional compiled binaries for all platforms and I'm not certain it would be worthwhile to do.

If you have feedback or advice on the course of actions to take on this matter, I would be grateful for your input! In the meantime, I would kindly ask you to use the latest version of QuantCrypt with Python version 3.12.

EDIT: I simplified the solution to this issue by yanking all releases prior to version 0.3.4, so now it should be impossible to unintentionally install an incompatible version of this library.

Whoops sorry about the delayed response. I supposed the only real solution for supporting multiple Python versions would be to build them in CI and then upload a .whl for each one. Maintaining libraries is hard. Thanks for the response! :)