From 9fa724b192810ede9e5bc5983fec63501162240a Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Fri, 1 Dec 2023 15:38:12 -0500 Subject: [PATCH 01/27] fixed shared lib detection code --- oqs/oqs.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 67a4820..76e5e1b 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -20,12 +20,19 @@ def _load_shared_obj(name): - """Attempts to load native OQS library.""" + """Attempts to load shared library.""" paths = [] # search typical locations - paths += [ctu.find_library(name)] - paths += [ctu.find_library("lib" + name)] + try: + paths += [ctu.find_library(name)] + except FileNotFoundError: + pass + try: + paths += [ctu.find_library("lib" + name)] + except FileNotFoundError: + pass + dll = ct.windll if platform.system() == "Windows" else ct.cdll for path in paths: From 8798f6d7e1bd3fc4f8667e9fbe91c8c8a88ada6e Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Fri, 15 Mar 2024 17:44:59 -0400 Subject: [PATCH 02/27] minor update --- examples/kem.py | 4 ++- oqs/oqs.py | 94 +++++++++++++++++++++++++++++++++++-------------- oqs/rand.py | 28 ++++++++++----- 3 files changed, 89 insertions(+), 37 deletions(-) diff --git a/examples/kem.py b/examples/kem.py index defa6b8..2ee2ce6 100644 --- a/examples/kem.py +++ b/examples/kem.py @@ -34,4 +34,6 @@ # the client decapsulates the server's ciphertext to obtain the shared secret shared_secret_client = client.decap_secret(ciphertext) - print("\nShared secretes coincide:", shared_secret_client == shared_secret_server) + print( + "\nShared secretes coincide:", shared_secret_client == shared_secret_server + ) diff --git a/oqs/oqs.py b/oqs/oqs.py index 76e5e1b..d41cebb 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -64,7 +64,7 @@ def native(): def oqs_version(): """liboqs version string.""" native().OQS_version.restype = ct.c_char_p - return ct.c_char_p(native().OQS_version()).value.decode('UTF-8') + return ct.c_char_p(native().OQS_version()).value.decode("UTF-8") def oqs_python_version(): @@ -79,7 +79,11 @@ def oqs_python_version(): # warn the use if the liboqs version differs from liboqs-python version if oqs_version() != oqs_python_version(): - warnings.warn("liboqs version {} differs from liboqs-python version {}".format(oqs_version(), oqs_python_version())) + warnings.warn( + "liboqs version {} differs from liboqs-python version {}".format( + oqs_version(), oqs_python_version() + ) + ) class MechanismNotSupportedError(Exception): @@ -129,7 +133,7 @@ class KeyEncapsulation(ct.Structure): ("length_shared_secret", ct.c_size_t), ("keypair_cb", ct.c_void_p), ("encaps_cb", ct.c_void_p), - ("decaps_cb", ct.c_void_p) + ("decaps_cb", ct.c_void_p), ] def __init__(self, alg_name, secret_key=None): @@ -159,10 +163,13 @@ def __init__(self, alg_name, secret_key=None): "length_public_key": int(self._kem.contents.length_public_key), "length_secret_key": int(self._kem.contents.length_secret_key), "length_ciphertext": int(self._kem.contents.length_ciphertext), - "length_shared_secret": int(self._kem.contents.length_shared_secret)} + "length_shared_secret": int(self._kem.contents.length_shared_secret), + } if secret_key: - self.secret_key = ct.create_string_buffer(secret_key, self._kem.contents.length_secret_key) + self.secret_key = ct.create_string_buffer( + secret_key, self._kem.contents.length_secret_key + ) def __enter__(self): return self @@ -178,7 +185,9 @@ def generate_keypair(self): """ public_key = ct.create_string_buffer(self._kem.contents.length_public_key) self.secret_key = ct.create_string_buffer(self._kem.contents.length_secret_key) - rv = native().OQS_KEM_keypair(self._kem, ct.byref(public_key), ct.byref(self.secret_key)) + rv = native().OQS_KEM_keypair( + self._kem, ct.byref(public_key), ct.byref(self.secret_key) + ) return bytes(public_key) if rv == OQS_SUCCESS else 0 def export_secret_key(self): @@ -191,10 +200,14 @@ def encap_secret(self, public_key): :param public_key: the peer's public key. """ - my_public_key = ct.create_string_buffer(public_key, self._kem.contents.length_public_key) + my_public_key = ct.create_string_buffer( + public_key, self._kem.contents.length_public_key + ) ciphertext = ct.create_string_buffer(self._kem.contents.length_ciphertext) shared_secret = ct.create_string_buffer(self._kem.contents.length_shared_secret) - rv = native().OQS_KEM_encaps(self._kem, ct.byref(ciphertext), ct.byref(shared_secret), my_public_key) + rv = native().OQS_KEM_encaps( + self._kem, ct.byref(ciphertext), ct.byref(shared_secret), my_public_key + ) return bytes(ciphertext), bytes(shared_secret) if rv == OQS_SUCCESS else 0 def decap_secret(self, ciphertext): @@ -203,15 +216,21 @@ def decap_secret(self, ciphertext): :param ciphertext: the ciphertext received from the peer. """ - my_ciphertext = ct.create_string_buffer(ciphertext, self._kem.contents.length_ciphertext) + my_ciphertext = ct.create_string_buffer( + ciphertext, self._kem.contents.length_ciphertext + ) shared_secret = ct.create_string_buffer(self._kem.contents.length_shared_secret) - rv = native().OQS_KEM_decaps(self._kem, ct.byref(shared_secret), my_ciphertext, self.secret_key) + rv = native().OQS_KEM_decaps( + self._kem, ct.byref(shared_secret), my_ciphertext, self.secret_key + ) return bytes(shared_secret) if rv == OQS_SUCCESS else 0 def free(self): """Releases the native resources.""" if hasattr(self, "secret_key"): - native().OQS_MEM_cleanse(ct.byref(self.secret_key), self._kem.contents.length_secret_key) + native().OQS_MEM_cleanse( + ct.byref(self.secret_key), self._kem.contents.length_secret_key + ) native().OQS_KEM_free(self._kem) def __repr__(self): @@ -231,7 +250,9 @@ def is_kem_enabled(alg_name): return native().OQS_KEM_alg_is_enabled(ct.create_string_buffer(alg_name.encode())) -_KEM_alg_ids = [native().OQS_KEM_alg_identifier(i) for i in range(native().OQS_KEM_alg_count())] +_KEM_alg_ids = [ + native().OQS_KEM_alg_identifier(i) for i in range(native().OQS_KEM_alg_count()) +] _supported_KEMs = [i.decode() for i in _KEM_alg_ids] _enabled_KEMs = [i for i in _supported_KEMs if is_kem_enabled(i)] @@ -270,7 +291,7 @@ class Signature(ct.Structure): ("length_signature", ct.c_size_t), ("keypair_cb", ct.c_void_p), ("sign_cb", ct.c_void_p), - ("verify_cb", ct.c_void_p) + ("verify_cb", ct.c_void_p), ] def __init__(self, alg_name, secret_key=None): @@ -297,10 +318,13 @@ def __init__(self, alg_name, secret_key=None): "is_euf_cma": bool(self._sig.contents.euf_cma), "length_public_key": int(self._sig.contents.length_public_key), "length_secret_key": int(self._sig.contents.length_secret_key), - "length_signature": int(self._sig.contents.length_signature)} + "length_signature": int(self._sig.contents.length_signature), + } if secret_key: - self.secret_key = ct.create_string_buffer(secret_key, self._sig.contents.length_secret_key) + self.secret_key = ct.create_string_buffer( + secret_key, self._sig.contents.length_secret_key + ) def __enter__(self): return self @@ -316,7 +340,9 @@ def generate_keypair(self): """ public_key = ct.create_string_buffer(self._sig.contents.length_public_key) self.secret_key = ct.create_string_buffer(self._sig.contents.length_secret_key) - rv = native().OQS_SIG_keypair(self._sig, ct.byref(public_key), ct.byref(self.secret_key)) + rv = native().OQS_SIG_keypair( + self._sig, ct.byref(public_key), ct.byref(self.secret_key) + ) return bytes(public_key) if rv == OQS_SUCCESS else 0 def export_secret_key(self): @@ -333,12 +359,19 @@ def sign(self, message): my_message = ct.create_string_buffer(message, len(message)) message_len = ct.c_int(len(my_message)) signature = ct.create_string_buffer(self._sig.contents.length_signature) - sig_len = ct.c_int(self._sig.contents.length_signature) # initialize to maximum signature size - rv = native().OQS_SIG_sign(self._sig, ct.byref(signature), - ct.byref(sig_len), my_message, - message_len, self.secret_key) - - return bytes(signature[:sig_len.value]) if rv == OQS_SUCCESS else 0 + sig_len = ct.c_int( + self._sig.contents.length_signature + ) # initialize to maximum signature size + rv = native().OQS_SIG_sign( + self._sig, + ct.byref(signature), + ct.byref(sig_len), + my_message, + message_len, + self.secret_key, + ) + + return bytes(signature[: sig_len.value]) if rv == OQS_SUCCESS else 0 def verify(self, message, signature, public_key): """ @@ -355,15 +388,20 @@ def verify(self, message, signature, public_key): # provide length to avoid extra null char in sig my_signature = ct.create_string_buffer(signature, len(signature)) sig_len = ct.c_int(len(my_signature)) - my_public_key = ct.create_string_buffer(public_key, self._sig.contents.length_public_key) - rv = native().OQS_SIG_verify(self._sig, my_message, message_len, - my_signature, sig_len, my_public_key) + my_public_key = ct.create_string_buffer( + public_key, self._sig.contents.length_public_key + ) + rv = native().OQS_SIG_verify( + self._sig, my_message, message_len, my_signature, sig_len, my_public_key + ) return True if rv == OQS_SUCCESS else False def free(self): """Releases the native resources.""" if hasattr(self, "secret_key"): - native().OQS_MEM_cleanse(ct.byref(self.secret_key), self._sig.contents.length_secret_key) + native().OQS_MEM_cleanse( + ct.byref(self.secret_key), self._sig.contents.length_secret_key + ) native().OQS_SIG_free(self._sig) def __repr__(self): @@ -383,7 +421,9 @@ def is_sig_enabled(alg_name): return native().OQS_SIG_alg_is_enabled(ct.create_string_buffer(alg_name.encode())) -_sig_alg_ids = [native().OQS_SIG_alg_identifier(i) for i in range(native().OQS_SIG_alg_count())] +_sig_alg_ids = [ + native().OQS_SIG_alg_identifier(i) for i in range(native().OQS_SIG_alg_count()) +] _supported_sigs = [i.decode() for i in _sig_alg_ids] _enabled_sigs = [i for i in _supported_sigs if is_sig_enabled(i)] diff --git a/oqs/rand.py b/oqs/rand.py index e5d0a7c..339ea87 100644 --- a/oqs/rand.py +++ b/oqs/rand.py @@ -29,9 +29,13 @@ def randombytes_switch_algorithm(alg_name): :param alg_name: algorithm name, possible values are "system", "NIST-KAT", "OpenSSL". """ - if oqs.native().OQS_randombytes_switch_algorithm( - oqs.ct.create_string_buffer(alg_name.encode())) != oqs.OQS_SUCCESS: - raise RuntimeError('Can not switch algorithm') + if ( + oqs.native().OQS_randombytes_switch_algorithm( + oqs.ct.create_string_buffer(alg_name.encode()) + ) + != oqs.OQS_SUCCESS + ): + raise RuntimeError("Can not switch algorithm") def randombytes_nist_kat_init_256bit(entropy_input, personalization_string=None): @@ -42,12 +46,18 @@ def randombytes_nist_kat_init_256bit(entropy_input, personalization_string=None) :param personalization_string: optional personalization string, which, if present, must be at least 48 bytes long. """ if len(entropy_input) != 48: - raise ValueError('The entropy source must be exactly 48 bytes long') + raise ValueError("The entropy source must be exactly 48 bytes long") if personalization_string is not None: if len(personalization_string) < 48: - raise ValueError('The personalization string must be either empty or at least 48 bytes long') - oqs.native().OQS_randombytes_nist_kat_init_256bit(oqs.ct.create_string_buffer(entropy_input), - oqs.ct.create_string_buffer(personalization_string)) - - oqs.native().OQS_randombytes_nist_kat_init_256bit(oqs.ct.create_string_buffer(entropy_input), 0) + raise ValueError( + "The personalization string must be either empty or at least 48 bytes long" + ) + oqs.native().OQS_randombytes_nist_kat_init_256bit( + oqs.ct.create_string_buffer(entropy_input), + oqs.ct.create_string_buffer(personalization_string), + ) + + oqs.native().OQS_randombytes_nist_kat_init_256bit( + oqs.ct.create_string_buffer(entropy_input), 0 + ) From 9eae46b6b56f123d6c07875ebec7e1d9ef23ab5d Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Tue, 26 Mar 2024 17:30:24 -0400 Subject: [PATCH 03/27] Update --- CHANGES.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ CHANGES.txt | 1 + LICENSE | 2 +- README.md | 6 +++--- RELEASE.md | 34 +++++++++++++++++------------- examples/rand.py | 27 +++++++++++------------- pyproject.toml | 4 ++-- 7 files changed, 93 insertions(+), 36 deletions(-) create mode 100644 CHANGES.md diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..ecc3677 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,55 @@ +# Version 0.10.0 - March 27, 2024 + +- Removed the NIST PRNG as the latter is no longer exposed by liboqs' public + API + +# Version 0.9.0 - October 30, 2023 + +- This is a maintenance release, minor deprecation fixes +- Python minimum required version is enforced to Python 3.8 in `pyproject.toml` +- To follow Python conventions, renamed in `oqs/oqs.py`: + - `is_KEM_enabled()` -> `is_kem_enabled()` + - `get_enabled_KEM_mechanisms()` -> `get_enabled_kem_mechanisms()` + - `get_supported_KEM_mechanisms()` -> `get_supported_kem_mechanisms()` + +# Version 0.8.0 - July 5, 2023 + +- This is a maintenance release, minor fixes +- Minimalistic Docker support +- Migrated installation method to `pyproject.toml` +- Removed AppVeyor and CircleCI, all continuous integration is now done via GitHub actions + +# Version 0.7.2 - August 27, 2022 + +- Added library version retrieval functions: + - `oqs_version()` + - `oqs_python_version()` + +# Version 0.7.1 - January 5, 2022 + +- Release numbering updated to match liboqs +- Added macOS support on CircleCI, we now support macOS & Linux (CircleCI) and Windows (AppVeyor) + +# Version 0.4.0 - November 28, 2020 + +- Renamed 'master' branch to 'main' + +# Version 0.3.0 - June 10, 2020 + +- The liboqs handle has now module-private visibility in `oqs.py` so clients can not access it directly; can be accessed via the new `oqs.native()` function +- Closing #7 [link](https://github.com/open-quantum-safe/liboqs-python/issues/7), all issues addressed +- Added AppVeyor continuous integration + +# Version 0.2.1 - January 22, 2020 + +- Added a signature example +- Added partial support for RNGs from `` +- Added an RNG example + +# Version 0.2.0 - October 8, 2019 + +- This release updates for compatibility with liboqs 0.2.0, which contains new/updated algorithms based on NIST Round 2 submissions. + +# Version 0.1.0 - April 23, 2019 + +- Initial release diff --git a/CHANGES.txt b/CHANGES.txt index ff8b28e..3c052b8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,6 +5,7 @@ Version 0.9.0 - October 30, 2023 is_KEM_enabled() -> is_kem_enabled() get_enabled_KEM_mechanisms() -> get_enabled_kem_mechanisms() get_supported_KEM_mechanisms() -> get_supported_kem_mechanisms() + - Removed the NIST PRNG as the later is no longer exposed by liboqs' public API Version 0.8.0 - July 5, 2023 - This is a maintenance release, minor fixes diff --git a/LICENSE b/LICENSE index 25b4126..1fe6778 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2023 Open Quantum Safe +Copyright (c) 2018-2024 Open Quantum Safe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 75feb52..b78118b 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ cmake -S liboqs -B liboqs/build -DCMAKE_INSTALL_PREFIX="C:\liboqs" -DBUILD_SHARE Execute in a Terminal/Console/Administrator Command Prompt ```shell -python3 -mvenv venv +python3 -mvenv venv . venv/bin/activate python3 -m ensurepip --upgrade ``` @@ -185,7 +185,7 @@ In case you want to use the Docker container as a development environment, mount container with ```shell -docker run --rm -it --workdir=/app -v ${PWD}:/app oqs-python /bin/bash +docker run --rm -it --workdir=/app -v ${PWD}:/app oqs-python /bin/bash ``` A more comprehensive Docker example is provided in the @@ -232,7 +232,7 @@ and [Michele Mosca](http://faculty.iqc.uwaterloo.ca/mmosca/) at the University o Contributors to the liboqs-python wrapper include: - Ben Davies (University of Waterloo) -- Vlad Gheorghiu (softwareQ Inc., University of Waterloo) +- Vlad Gheorghiu ([softwareQ Inc.](https://www.softwareq.ca) and the University of Waterloo) - Christian Paquin (Microsoft Research) - Douglas Stebila (University of Waterloo) diff --git a/RELEASE.md b/RELEASE.md index 6aa19e5..93f1be9 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,32 +1,36 @@ -# liboqs-python version 0.9.0 +# liboqs-python version 0.10.0 --- ## About -The **Open Quantum Safe (OQS) project** has the goal of developing and prototyping quantum-resistant cryptography. More -information on OQS can be found on our website https://openquantumsafe.org/ and on GitHub -at https://github.com/open-quantum-safe/. +The **Open Quantum Safe (OQS) project** has the goal of developing and +prototyping quantum-resistant cryptography. More information on OQS can be +found on our website https://openquantumsafe.org/ and on GitHub at +https://github.com/open-quantum-safe/. -**liboqs** is an open source C library for quantum-resistant cryptographic algorithms. See more about liboqs -at [https://github.com/open-quantum-safe/liboqs/](https://github.com/open-quantum-safe/liboqs/), including a list of -supported algorithms. +**liboqs** is an open source C library for quantum-resistant cryptographic +algorithms. See more about liboqs at +[https://github.com/open-quantum-safe/liboqs/](https://github.com/open-quantum-safe/liboqs/), +including a list of supported algorithms. -**liboqs-python** is an open source Python 3 wrapper for the liboqs C library for quantum-resistant cryptographic -algorithms. Details about liboqs-python can be found -in [README.md](https://github.com/open-quantum-safe/liboqs-python/blob/main/README.md). See in particular limitations on -intended use. +**liboqs-python** is an open source Python 3 wrapper for the liboqs C library +for quantum-resistant cryptographic algorithms. Details about liboqs-python can +be found in +[README.md](https://github.com/open-quantum-safe/liboqs-python/blob/main/README.md). +See in particular limitations on intended use. --- ## Release notes -This release of liboqs-python was released on October 30, 2023. Its release page on GitHub -is https://github.com/open-quantum-safe/liboqs-python/releases/tag/0.9.0. +This release of liboqs-python was released on October 30, 2023. Its release +page on GitHub is +https://github.com/open-quantum-safe/liboqs-python/releases/tag/0.9.0. --- ## What's New -This is the 9th release of liboqs-python. For a list of changes -see [CHANGES.txt](https://github.com/open-quantum-safe/liboqs-python/blob/main/CHANGES.txt). +This is the 10th release of liboqs-python. For a list of changes see +[CHANGES.txt](https://github.com/open-quantum-safe/liboqs-python/blob/main/CHANGES.txt). diff --git a/examples/rand.py b/examples/rand.py index 7aadfea..c45de6b 100644 --- a/examples/rand.py +++ b/examples/rand.py @@ -1,29 +1,26 @@ -# various RNGs Python example +# Various RNGs Python example import platform # to learn the OS we're on import oqs.rand as oqsrand # must be explicitly imported from oqs import oqs_version, oqs_python_version ####################################################################### -# randomness example +# Randomness example ####################################################################### print("liboqs version:", oqs_version()) print("liboqs-python version:", oqs_python_version()) -# set the entropy seed to some values -entropy_seed = [0] * 48 -for i in range(0, 48): - entropy_seed[i] = i - -oqsrand.randombytes_nist_kat_init_256bit(bytes(entropy_seed)) -oqsrand.randombytes_switch_algorithm("NIST-KAT") -print('{:17s}'.format("NIST-KAT:"), ' '.join('{:02X}'.format(x) for x in oqsrand.randombytes(32))) +oqsrand.randombytes_switch_algorithm("system") +print( + "{:17s}".format("System (default):"), + " ".join("{:02X}".format(x) for x in oqsrand.randombytes(32)), +) -# we do not yet support OpenSSL under Windows +# We do not yet support OpenSSL under Windows if platform.system() != "Windows": oqsrand.randombytes_switch_algorithm("OpenSSL") - print('{:17s}'.format("OpenSSL:"), ' '.join('{:02X}'.format(x) for x in oqsrand.randombytes(32))) - -oqsrand.randombytes_switch_algorithm("system") -print('{:17s}'.format("System (default):"), ' '.join('{:02X}'.format(x) for x in oqsrand.randombytes(32))) + print( + "{:17s}".format("OpenSSL:"), + " ".join("{:02X}".format(x) for x in oqsrand.randombytes(32)), + ) diff --git a/pyproject.toml b/pyproject.toml index 0ec6314..fd558c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,8 +8,8 @@ build-backend = "setuptools.build_meta" [project] name = "liboqs-python" requires-python = ">=3.8" -version = "0.9.0" -description = "Python wrapper for liboqs, providing post-quantum public key cryptography algorithms" +version = "0.10.0" +description = "Python bindings for liboqs, providing post-quantum public key cryptography algorithms" authors = [ { name = "Open Quantum Safe project", email = "contact@openquantumsafe.org" }, ] From 726d682ac060cbb91952f1a47e9dcd2c2108bd73 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Wed, 27 Mar 2024 08:05:46 -0400 Subject: [PATCH 04/27] Code cleanup --- examples/kem.py | 19 ++++++++----------- examples/rand.py | 4 ---- examples/sig.py | 19 ++++++++----------- oqs/oqs.py | 11 ++++++----- oqs/rand.py | 10 +++++++--- tests/test_kem.py | 2 +- tests/test_sig.py | 2 +- 7 files changed, 31 insertions(+), 36 deletions(-) diff --git a/examples/kem.py b/examples/kem.py index 2ee2ce6..a9deb2d 100644 --- a/examples/kem.py +++ b/examples/kem.py @@ -1,37 +1,34 @@ -# key encapsulation Python example +# Key encapsulation Python example import oqs from pprint import pprint -####################################################################### -# KEM example -####################################################################### - print("liboqs version:", oqs.oqs_version()) print("liboqs-python version:", oqs.oqs_python_version()) print("Enabled KEM mechanisms:") kems = oqs.get_enabled_kem_mechanisms() pprint(kems, compact=True) -# create client and server with sample KEM mechanisms +# Create client and server with sample KEM mechanisms kemalg = "Kyber512" with oqs.KeyEncapsulation(kemalg) as client: with oqs.KeyEncapsulation(kemalg) as server: print("\nKey encapsulation details:") pprint(client.details) - # client generates its keypair + # Client generates its keypair public_key_client = client.generate_keypair() - # optionally, the secret key can be obtained by calling export_secret_key() + # Optionally, the secret key can be obtained by calling export_secret_key() # and the client can later be re-instantiated with the key pair: # secret_key_client = client.export_secret_key() - # store key pair, wait... (session resumption): + + # Store key pair, wait... (session resumption): # client = oqs.KeyEncapsulation(kemalg, secret_key_client) - # the server encapsulates its secret using the client's public key + # The server encapsulates its secret using the client's public key ciphertext, shared_secret_server = server.encap_secret(public_key_client) - # the client decapsulates the server's ciphertext to obtain the shared secret + # The client decapsulates the server's ciphertext to obtain the shared secret shared_secret_client = client.decap_secret(ciphertext) print( diff --git a/examples/rand.py b/examples/rand.py index c45de6b..75e5c89 100644 --- a/examples/rand.py +++ b/examples/rand.py @@ -4,10 +4,6 @@ import oqs.rand as oqsrand # must be explicitly imported from oqs import oqs_version, oqs_python_version -####################################################################### -# Randomness example -####################################################################### - print("liboqs version:", oqs_version()) print("liboqs-python version:", oqs_python_version()) diff --git a/examples/sig.py b/examples/sig.py index f800245..ea07508 100644 --- a/examples/sig.py +++ b/examples/sig.py @@ -1,12 +1,8 @@ -# signature Python example +# Signature Python example import oqs from pprint import pprint -####################################################################### -# signature example -####################################################################### - print("liboqs version:", oqs.oqs_version()) print("liboqs-python version:", oqs.oqs_python_version()) print("Enabled signature mechanisms:") @@ -15,25 +11,26 @@ message = "This is the message to sign".encode() -# create signer and verifier with sample signature mechanisms +# Create signer and verifier with sample signature mechanisms sigalg = "Dilithium2" with oqs.Signature(sigalg) as signer: with oqs.Signature(sigalg) as verifier: print("\nSignature details:") pprint(signer.details) - # signer generates its keypair + # Signer generates its keypair signer_public_key = signer.generate_keypair() - # optionally, the secret key can be obtained by calling export_secret_key() + # Optionally, the secret key can be obtained by calling export_secret_key() # and the signer can later be re-instantiated with the key pair: # secret_key = signer.export_secret_key() - # store key pair, wait... (session resumption): + + # Store key pair, wait... (session resumption): # signer = oqs.Signature(sigalg, secret_key) - # signer signs the message + # Signer signs the message signature = signer.sign(message) - # verifier verifies the signature + # Verifier verifies the signature is_valid = verifier.verify(message, signature, signer_public_key) print("\nValid signature?", is_valid) diff --git a/oqs/oqs.py b/oqs/oqs.py index 4b76630..2b22ed0 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -14,7 +14,7 @@ import sys import warnings -# expected return value from native OQS functions +# Expected return value from native OQS functions OQS_SUCCESS = 0 OQS_ERROR = -1 @@ -42,6 +42,7 @@ def _load_shared_obj(name): raise RuntimeError("No " + name + " shared libraries found") + try: _liboqs = _load_shared_obj("oqs") assert _liboqs @@ -76,7 +77,7 @@ def oqs_python_version(): return result -# warn the use if the liboqs version differs from liboqs-python version +# Warn the use if the liboqs version differs from liboqs-python version if oqs_version() != oqs_python_version(): warnings.warn( "liboqs version {} differs from liboqs-python version {}".format( @@ -354,7 +355,7 @@ def sign(self, message): :param message: the message to sign. """ - # provide length to avoid extra null char + # Provide length to avoid extra null char my_message = ct.create_string_buffer(message, len(message)) message_len = ct.c_int(len(my_message)) signature = ct.create_string_buffer(self._sig.contents.length_signature) @@ -380,11 +381,11 @@ def verify(self, message, signature, public_key): :param signature: the signature on the message. :param public_key: the signer's public key. """ - # provide length to avoid extra null char + # Provide length to avoid extra null char my_message = ct.create_string_buffer(message, len(message)) message_len = ct.c_int(len(my_message)) - # provide length to avoid extra null char in sig + # Provide length to avoid extra null char in sig my_signature = ct.create_string_buffer(signature, len(signature)) sig_len = ct.c_int(len(my_signature)) my_public_key = ct.create_string_buffer( diff --git a/oqs/rand.py b/oqs/rand.py index ffe3fc5..5e7fd77 100644 --- a/oqs/rand.py +++ b/oqs/rand.py @@ -29,6 +29,10 @@ def randombytes_switch_algorithm(alg_name): :param alg_name: algorithm name, possible values are "system" and "OpenSSL". """ - if oqs.native().OQS_randombytes_switch_algorithm( - oqs.ct.create_string_buffer(alg_name.encode())) != oqs.OQS_SUCCESS: - raise RuntimeError('Can not switch algorithm') + if ( + oqs.native().OQS_randombytes_switch_algorithm( + oqs.ct.create_string_buffer(alg_name.encode()) + ) + != oqs.OQS_SUCCESS + ): + raise RuntimeError("Can not switch algorithm") diff --git a/tests/test_kem.py b/tests/test_kem.py index b2b2fac..226bbfa 100644 --- a/tests/test_kem.py +++ b/tests/test_kem.py @@ -64,7 +64,7 @@ def test_not_enabled(): raise AssertionError("An unexpected exception was raised. " + ex) -if __name__ == '__main__': +if __name__ == "__main__": try: import nose2 diff --git a/tests/test_sig.py b/tests/test_sig.py index b03003d..41cb887 100644 --- a/tests/test_sig.py +++ b/tests/test_sig.py @@ -96,7 +96,7 @@ def test_not_enabled(): raise AssertionError("An unexpected exception was raised. " + ex) -if __name__ == '__main__': +if __name__ == "__main__": try: import nose2 From 51c912f1353ca43a70bbcca9a19cf775d2fff2d4 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Wed, 27 Mar 2024 15:51:29 -0400 Subject: [PATCH 05/27] Update --- CHANGES.md | 3 +++ CHANGES.txt | 48 ------------------------------------------------ RELEASE.md | 2 +- 3 files changed, 4 insertions(+), 49 deletions(-) delete mode 100644 CHANGES.txt diff --git a/CHANGES.md b/CHANGES.md index ecc3677..540adae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,8 @@ # Version 0.10.0 - March 27, 2024 +- Replaced CHANGES by + [CHANGES.md](https://github.com/open-quantum-safe/liboqs-python/blob/main/CHANGES.md), + as we now use Markdown format to keep track of changes in new releases - Removed the NIST PRNG as the latter is no longer exposed by liboqs' public API diff --git a/CHANGES.txt b/CHANGES.txt deleted file mode 100644 index 3c052b8..0000000 --- a/CHANGES.txt +++ /dev/null @@ -1,48 +0,0 @@ -Version 0.9.0 - October 30, 2023 - - This is a maintenance release, minor deprecation fixes - - Python minimum required version is enforced to Python 3.8 in pyproject.toml - - To follow Python conventions, renamed in "oqs/oqs.py" - is_KEM_enabled() -> is_kem_enabled() - get_enabled_KEM_mechanisms() -> get_enabled_kem_mechanisms() - get_supported_KEM_mechanisms() -> get_supported_kem_mechanisms() - - Removed the NIST PRNG as the later is no longer exposed by liboqs' public API - -Version 0.8.0 - July 5, 2023 - - This is a maintenance release, minor fixes - - Minimalistic Docker support - - Migrated installation method to pyproject.toml - - Removed AppVeyor and CircleCI, all continuous integration is now done - via GitHub actions - -Version 0.7.2 - August 27, 2022 - - Added library version retrieval functions - oqs_version() - oqs_python_version() - -Version 0.7.1 - January 5, 2022 - - Release numbering updated to match liboqs - - Added macOS support on CircleCI, we now support macOS & Linux (CircleCI) - and Windows (AppVeyor) - -Version 0.4.0 - November 28, 2020 - - Renamed 'master' branch to 'main' - -Version 0.3.0 - June 10, 2020 - - The liboqs handle has now module-private visibility in oqs.py so clients - can not access it directly; can be accessed via the new oqs.native() - function - - Closing #7 https://github.com/open-quantum-safe/liboqs-python/issues/7, - all issues addressed - - Added AppVeyor continuous integration - -Version 0.2.1 - January 22, 2020 - - Added a signature example - - Added partial support for RNGs from - - Added an RNG example - -Version 0.2.0 - October 8, 2019 - - This release updates for compatibility with liboqs 0.2.0, which contains - new/updated algorithms based on NIST Round 2 submissions. - -Version 0.1.0 - April 23, 2019 - - Initial release diff --git a/RELEASE.md b/RELEASE.md index 93f1be9..269f130 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -33,4 +33,4 @@ https://github.com/open-quantum-safe/liboqs-python/releases/tag/0.9.0. ## What's New This is the 10th release of liboqs-python. For a list of changes see -[CHANGES.txt](https://github.com/open-quantum-safe/liboqs-python/blob/main/CHANGES.txt). +[CHANGES.md](https://github.com/open-quantum-safe/liboqs-python/blob/main/CHANGES.md). From c666a17f60236827693770f877828d1143df6e30 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Wed, 27 Mar 2024 16:10:03 -0400 Subject: [PATCH 06/27] Minor cleanups --- CHANGES.md | 19 +++++-- README.md | 138 ++++++++++++++++++++++++++-------------------- docker/README.md | 24 ++++---- tests/test_kem.py | 2 +- tests/test_sig.py | 4 +- 5 files changed, 109 insertions(+), 78 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 540adae..daf8357 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -# Version 0.10.0 - March 27, 2024 +# Version 0.10.0 - March 28, 2024 - Replaced CHANGES by [CHANGES.md](https://github.com/open-quantum-safe/liboqs-python/blob/main/CHANGES.md), @@ -20,7 +20,8 @@ - This is a maintenance release, minor fixes - Minimalistic Docker support - Migrated installation method to `pyproject.toml` -- Removed AppVeyor and CircleCI, all continuous integration is now done via GitHub actions +- Removed AppVeyor and CircleCI, all continuous integration is now done via + GitHub actions # Version 0.7.2 - August 27, 2022 @@ -31,7 +32,8 @@ # Version 0.7.1 - January 5, 2022 - Release numbering updated to match liboqs -- Added macOS support on CircleCI, we now support macOS & Linux (CircleCI) and Windows (AppVeyor) +- Added macOS support on CircleCI, we now support macOS & Linux (CircleCI) and + Windows (AppVeyor) # Version 0.4.0 - November 28, 2020 @@ -39,8 +41,12 @@ # Version 0.3.0 - June 10, 2020 -- The liboqs handle has now module-private visibility in `oqs.py` so clients can not access it directly; can be accessed via the new `oqs.native()` function -- Closing #7 [link](https://github.com/open-quantum-safe/liboqs-python/issues/7), all issues addressed +- The liboqs handle has now module-private visibility in `oqs.py` so clients + can not access it directly; can be accessed via the new `oqs.native()` + function +- Closing + #7 [link](https://github.com/open-quantum-safe/liboqs-python/issues/7), all + issues addressed - Added AppVeyor continuous integration # Version 0.2.1 - January 22, 2020 @@ -51,7 +57,8 @@ # Version 0.2.0 - October 8, 2019 -- This release updates for compatibility with liboqs 0.2.0, which contains new/updated algorithms based on NIST Round 2 submissions. +- This release updates for compatibility with liboqs 0.2.0, which contains + new/updated algorithms based on NIST Round 2 submissions. # Version 0.1.0 - April 23, 2019 diff --git a/README.md b/README.md index b78118b..0f207a6 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,18 @@ ## About -The **Open Quantum Safe (OQS) project** has the goal of developing and prototyping quantum-resistant cryptography. +The **Open Quantum Safe (OQS) project** has the goal of developing and +prototyping quantum-resistant cryptography. -**liboqs-python** offers a Python 3 wrapper for -the [Open Quantum Safe](https://openquantumsafe.org/) [liboqs](https://github.com/open-quantum-safe/liboqs/) +**liboqs-python** offers a Python 3 wrapper for the +[Open Quantum Safe](https://openquantumsafe.org/) +[liboqs](https://github.com/open-quantum-safe/liboqs/) C library, which is a C library for quantum-resistant cryptographic algorithms. -The wrapper is written in Python 3, hence in the following it is assumed that you have access to a Python 3 interpreter. -liboqs-python has been extensively tested on Linux, macOS and Windows platforms. Continuous integration is provided via -GitHub actions. +The wrapper is written in Python 3, hence in the following it is assumed that +you have access to a Python 3 interpreter. liboqs-python has been extensively +tested on Linux, macOS and Windows platforms. Continuous integration is +provided via GitHub actions. The project contains the following files and directories: @@ -32,8 +35,8 @@ The project contains the following files and directories: - [liboqs](https://github.com/open-quantum-safe/liboqs) - [CMake](https://cmake.org/) - C compliant compiler, - e.g., [gcc](https://gcc.gnu.org/), [clang](https://clang.llvm.org), [MSVC](https://visualstudio.microsoft.com/vs/) - etc. + e.g., [gcc](https://gcc.gnu.org/), [clang](https://clang.llvm.org), + [MSVC](https://visualstudio.microsoft.com/vs/) etc. - [Python 3 interpreter](https://www.python.org/) --- @@ -51,26 +54,29 @@ cmake --build liboqs/build --parallel 8 cmake --build liboqs/build --target install ``` -The last line may require prefixing it by `sudo` on UNIX-like systems. Change `--parallel 8` to match the number of -available cores on your system. +The last line may require prefixing it by `sudo` on UNIX-like systems. Change +`--parallel 8` to match the number of available cores on your system. -On UNIX-like platforms, you may need to set the `LD_LIBRARY_PATH` (`DYLD_LIBRARY_PATH` on macOS) environment variable to -point to the path to liboqs' library directory, e.g., +On UNIX-like platforms, you may need to set the `LD_LIBRARY_PATH` +(`DYLD_LIBRARY_PATH` on macOS) environment variable to point to the path to +liboqs' library directory, e.g., ```shell export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib ``` -On Windows platforms, **you must ensure** that the liboqs shared library `oqs.dll` is visible system-wide, and that the -following environment variable are being set. Use the "Edit the system environment variables" Control Panel tool or -execute in a Command Prompt, e.g., +On Windows platforms, **you must ensure** that the liboqs shared library +`oqs.dll` is visible system-wide, and that the following environment variable +are being set. Use the "Edit the system environment variables" Control Panel +tool or execute in a Command Prompt, e.g., ```shell set PATH=%PATH%;C:\Program Files (x86)\liboqs\bin ``` -You can change liboqs' installation directory by configuring the build to use an alternative path, e.g., `C:\liboqs`, by -replacing the first CMake line above by +You can change liboqs' installation directory by configuring the build to use +an alternative path, e.g., `C:\liboqs`, by replacing the first CMake line above +by ```shell cmake -S liboqs -B liboqs/build -DCMAKE_INSTALL_PREFIX="C:\liboqs" -DBUILD_SHARED_LIBS=ON @@ -136,21 +142,23 @@ liboqs-python can be imported into Python programs with import oqs ``` -liboqs-python defines two main classes: `KeyEncapsulation` and `Signature`, providing post-quantum key encapsulation and -signture mechanisms, respectively. Each must be instantiated with a string identifying one of mechanisms supported by -liboqs; these can be enumerated using the `get_enabled_KEM_mechanisms()` and `get_enabled_sig_mechanisms()` functions. -The files in `examples/` demonstrate the wrapper's API. Support for alternative RNGs is provided via -the `randombytes_*()` -functions. +liboqs-python defines two main classes: `KeyEncapsulation` and `Signature`, +providing post-quantum key encapsulation and signture mechanisms, respectively. +Each must be instantiated with a string identifying one of mechanisms supported +by liboqs; these can be enumerated using the `get_enabled_KEM_mechanisms()` and +`get_enabled_sig_mechanisms()` functions. The files in `examples/` demonstrate +the wrapper's API. Support for alternative RNGs is provided via the +`randombytes_*()` functions. -The liboqs-python project should be in the `PYTHONPATH`. To ensure this on UNIX-like systems, execute +The liboqs-python project should be in the `PYTHONPATH`. To ensure this on +UNIX-like systems, execute ```shell export PYTHONPATH=$PYTHONPATH:/path/to/liboqs-python ``` -or, on Windows platforms, use the "Edit the system environment variables" Control Panel tool or execute in a Command -Prompt +or, on Windows platforms, use the "Edit the system environment variables" +Control Panel tool or execute in a Command Prompt ```shell set PYTHONPATH=%PYTHONPATH%;C:\path\to\liboqs-python @@ -160,8 +168,8 @@ set PYTHONPATH=%PYTHONPATH%;C:\path\to\liboqs-python ## Docker -A self-explanatory minimalistic Docker file is provided -in [`Dockerfile`](https://github.com/open-quantum-safe/liboqs-python/tree/main/Dockerfile). +A self-explanatory minimalistic Docker file is provided in +[`Dockerfile`](https://github.com/open-quantum-safe/liboqs-python/tree/main/Dockerfile). Build the image by executing @@ -181,58 +189,68 @@ Or, run the unit tests with docker run -it oqs-python sh -c ". venv/bin/activate && nose2 --verbose liboqs-python" ``` -In case you want to use the Docker container as a development environment, mount your current project in the Docker -container with +In case you want to use the Docker container as a development environment, +mount your current project in the Docker container with ```shell docker run --rm -it --workdir=/app -v ${PWD}:/app oqs-python /bin/bash ``` -A more comprehensive Docker example is provided in the -directory [`docker`](https://github.com/open-quantum-safe/liboqs-python/tree/main/docker). +A more comprehensive Docker example is provided in the directory +[`docker`](https://github.com/open-quantum-safe/liboqs-python/tree/main/docker). --- ## Limitations and security -liboqs is designed for prototyping and evaluating quantum-resistant cryptography. Security of proposed quantum-resistant -algorithms may rapidly change as research advances, and may ultimately be completely insecure against either classical -or quantum computers. - -We believe that the NIST Post-Quantum Cryptography standardization project is currently the best avenue to identifying -potentially quantum-resistant algorithms. liboqs does not intend to "pick winners", and we strongly recommend that -applications and protocols rely on the outcomes of the NIST standardization project when deploying post-quantum -cryptography. - -We acknowledge that some parties may want to begin deploying post-quantum cryptography prior to the conclusion of the -NIST standardization project. We strongly recommend that any attempts to do make use of so-called -**hybrid cryptography**, in which post-quantum public-key algorithms are used alongside traditional public key -algorithms (like RSA or elliptic curves) so that the solution is at least no less secure than existing traditional +liboqs is designed for prototyping and evaluating quantum-resistant +cryptography. Security of proposed quantum-resistant algorithms may rapidly +change as research advances, and may ultimately be completely insecure against +either classical or quantum computers. + +We believe that the NIST Post-Quantum Cryptography standardization project is +currently the best avenue to identifying potentially quantum-resistant +algorithms. liboqs does not intend to "pick winners", and we strongly recommend +that applications and protocols rely on the outcomes of the NIST +standardization project when deploying post-quantum cryptography. + +We acknowledge that some parties may want to begin deploying post-quantum +cryptography prior to the conclusion of the NIST standardization project. We +strongly recommend that any attempts to do make use of so-called +**hybrid cryptography**, in which post-quantum public-key algorithms are used +alongside traditional public key algorithms (like RSA or elliptic curves) so +that the solution is at least no less secure than existing traditional cryptography. -Just like liboqs, liboqs-python is provided "as is", without warranty of any kind. -See [LICENSE](https://github.com/open-quantum-safe/liboqs-python/blob/main/LICENSE) for the full disclaimer. +Just like liboqs, liboqs-python is provided "as is", without warranty of any +kind. See +[LICENSE](https://github.com/open-quantum-safe/liboqs-python/blob/main/LICENSE) +for the full disclaimer. --- ## License -liboqs-python is licensed under the MIT License; -see [LICENSE](https://github.com/open-quantum-safe/liboqs-python/blob/main/LICENSE) for details. +liboqs-python is licensed under the MIT License; see +[LICENSE](https://github.com/open-quantum-safe/liboqs-python/blob/main/LICENSE) +for details. --- ## Team -The Open Quantum Safe project is led by [Douglas Stebila](https://www.douglas.stebila.ca/research/) -and [Michele Mosca](http://faculty.iqc.uwaterloo.ca/mmosca/) at the University of Waterloo. +The Open Quantum Safe project is led by +[Douglas Stebila](https://www.douglas.stebila.ca/research/) and +[Michele Mosca](http://faculty.iqc.uwaterloo.ca/mmosca/) at the University of +Waterloo. ### Contributors Contributors to the liboqs-python wrapper include: - Ben Davies (University of Waterloo) -- Vlad Gheorghiu ([softwareQ Inc.](https://www.softwareq.ca) and the University of Waterloo) +- Vlad Gheorghiu ([softwareQ Inc.](https://www.softwareq.ca) and the University + of Waterloo) - Christian Paquin (Microsoft Research) - Douglas Stebila (University of Waterloo) @@ -240,12 +258,14 @@ Contributors to the liboqs-python wrapper include: ## Support -Financial support for the development of Open Quantum Safe has been provided by Amazon Web Services and the Canadian -Centre for Cyber Security. +Financial support for the development of Open Quantum Safe has been provided by +Amazon Web Services and the Canadian Centre for Cyber Security. -We'd like to make a special acknowledgement to the companies who have dedicated programmer time to contribute source -code to OQS, including Amazon Web Services, evolutionQ, softwareQ, and Microsoft Research. +We'd like to make a special acknowledgement to the companies who have dedicated +programmer time to contribute source code to OQS, including Amazon Web +Services, evolutionQ, softwareQ, and Microsoft Research. -Research projects which developed specific components of OQS have been supported by various research grants, including -funding from the Natural Sciences and Engineering Research Council of Canada (NSERC); see the source papers for funding -acknowledgments. +Research projects which developed specific components of OQS have been +supported by various research grants, including funding from the Natural +Sciences and Engineering Research Council of Canada (NSERC); see the source +papers for funding acknowledgments. diff --git a/docker/README.md b/docker/README.md index 55da174..9109752 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,19 +1,23 @@ # OQS-python -This docker image contains python3 with library support for quantum-safe crypto (QSC) operations. +This docker image contains python3 with library support for quantum-safe crypto +(QSC) operations. -To this end, it contains [liboqs](https://github.com/open-quantum-safe/liboqs) as well -as [OQS-OpenSSL](https://github.com/open-quantum-safe/openssl) from the [OpenQuantumSafe](https://openquantumsafe.org) -project all wrapped up in Python APIs using [liboqs-python](https://github.com/open-quantum-safe/liboqs-python). +To this end, it contains [liboqs](https://github.com/open-quantum-safe/liboqs) +as well as [OQS-OpenSSL](https://github.com/open-quantum-safe/openssl) from the +[OpenQuantumSafe](https://openquantumsafe.org) project all wrapped up in Python +APIs using [liboqs-python](https://github.com/open-quantum-safe/liboqs-python). ## Quick start -- Executing `docker run -it openquantumsafe/python` tests all QSC algorithms against the interop server - at https://test.openquantumsafe.org. -- Executing `docker run -it openquantumsafe/python sh` provides a shell environment where liboqs and QSC-enabled SSL/TLS - is available for use. See the included file `minitest.py` for sample code exercizing this functionality. +- Executing `docker run -it openquantumsafe/python` tests all QSC algorithms + against the interop server at https://test.openquantumsafe.org. +- Executing `docker run -it openquantumsafe/python sh` provides a shell + environment where liboqs and QSC-enabled SSL/TLS is available for use. See + the included file `minitest.py` for sample code exercizing this + functionality. ## Further examples -More samples are available -at [liboqs-python examples](https://github.com/open-quantum-safe/liboqs-python/tree/main/examples). +More samples are available at +[liboqs-python examples](https://github.com/open-quantum-safe/liboqs-python/tree/main/examples). diff --git a/tests/test_kem.py b/tests/test_kem.py index 226bbfa..cd13640 100644 --- a/tests/test_kem.py +++ b/tests/test_kem.py @@ -54,7 +54,7 @@ def test_not_enabled(): # TODO: test broken as the compiled lib determines which algorithms are supported and enabled for alg_name in oqs.get_supported_kem_mechanisms(): if alg_name not in oqs.get_enabled_kem_mechanisms(): - # found a non-enabled but supported alg + # Found a non-enabled but supported alg try: with oqs.KeyEncapsulation(alg_name) as kem: raise AssertionError("oqs.MechanismNotEnabledError was not raised.") diff --git a/tests/test_sig.py b/tests/test_sig.py index 41cb887..5053df4 100644 --- a/tests/test_sig.py +++ b/tests/test_sig.py @@ -2,7 +2,7 @@ import platform # to learn the OS we're on import random -# sigs for which unit testing is disabled +# Sigs for which unit testing is disabled disabled_sig_patterns = [] if platform.system() == "Windows": @@ -86,7 +86,7 @@ def test_not_enabled(): # TODO: test broken as the compiled lib determines which algorithms are supported and enabled for alg_name in oqs.get_supported_sig_mechanisms(): if alg_name not in oqs.get_enabled_sig_mechanisms(): - # found a non-enabled but supported alg + # Found a non-enabled but supported alg try: with oqs.Signature(alg_name) as sig: raise AssertionError("oqs.MechanismNotEnabledError was not raised.") From b53cf20e1215536d5cea31b9e2c38c239fecd927 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Wed, 27 Mar 2024 17:28:01 -0400 Subject: [PATCH 07/27] First stab at automatic install --- oqs/oqs.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 2b22ed0..78c2e2f 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -10,8 +10,10 @@ import ctypes as ct # to call native import ctypes.util as ctu import importlib.metadata # to determine module version at runtime +import os # to run OS commands (install liboqs on demand if not found) import platform # to learn the OS we're on import sys +import tempfile # to install liboqs on demand import warnings # Expected return value from native OQS functions @@ -19,7 +21,7 @@ OQS_ERROR = -1 -def _load_shared_obj(name): +def _load_shared_obj(name, already_installed_liboqs): """Attempts to load shared library.""" paths = [] @@ -40,11 +42,53 @@ def _load_shared_obj(name): lib = dll.LoadLibrary(path) return lib - raise RuntimeError("No " + name + " shared libraries found") + if already_installed_liboqs: + raise RuntimeError("No " + name + " shared libraries found") + + # We don't have liboqs, so we try to install it + + with tempfile.TemporaryDirectory() as tmpdirname: + oqs_install_str_UNIX = ( + "cd " + + tmpdirname + + """ + + git clone https://github.com/open-quantum-safe/liboqs --depth 1 + cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON + cmake --build liboqs/build --parallel + sudo cmake --build liboqs/build --target install + """ + ) + + oqs_install_str_Windows = ( + "cd " + + tmpdirname + + """ + + git clone https://github.com/open-quantum-safe/liboqs --depth 1 + cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON + cmake --build liboqs/build --parallel + cmake --build liboqs/build --target install + """ + ) + + oqs_install_str = ( + oqs_install_str_Windows + if platform.system() == "Windows" + else oqs_install_str_UNIX + ) + + print("liboqs not found, downloading and installing liboqs in " + tmpdirname) + print("This process may ask for your admin password.") + input("Press ENTER to continue...") + os.system(oqs_install_str) + print("Done installing liboqs") + + return _load_shared_obj(name, already_installed_liboqs=True) try: - _liboqs = _load_shared_obj("oqs") + _liboqs = _load_shared_obj(name="oqs", already_installed_liboqs=False) assert _liboqs except OSError as err: sys.exit("Could not load liboqs shared library") From 7b04f1c04cb84e4e861ab6a5c2b9d06f82c7c005 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Wed, 27 Mar 2024 17:33:58 -0400 Subject: [PATCH 08/27] Updated CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index daf8357..f03ae45 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ as we now use Markdown format to keep track of changes in new releases - Removed the NIST PRNG as the latter is no longer exposed by liboqs' public API +- liboqs is now installed automatically if not detected at runtime # Version 0.9.0 - October 30, 2023 From 328253640c57a41c93ac18058e879d528f8017e0 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Wed, 27 Mar 2024 17:46:27 -0400 Subject: [PATCH 09/27] Minor update --- oqs/oqs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 78c2e2f..5de825a 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -55,7 +55,7 @@ def _load_shared_obj(name, already_installed_liboqs): git clone https://github.com/open-quantum-safe/liboqs --depth 1 cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON - cmake --build liboqs/build --parallel + cmake --build liboqs/build --parallel 4 sudo cmake --build liboqs/build --target install """ ) @@ -67,7 +67,7 @@ def _load_shared_obj(name, already_installed_liboqs): git clone https://github.com/open-quantum-safe/liboqs --depth 1 cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON - cmake --build liboqs/build --parallel + cmake --build liboqs/build --parallel 4 cmake --build liboqs/build --target install """ ) From ce3811a0001b22a87fe9e735be1a58c6206e1188 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Thu, 28 Mar 2024 10:26:27 -0400 Subject: [PATCH 10/27] Refactoring --- oqs/oqs.py | 55 ++++++++++++++++++------------------------------------ setup.py | 2 +- 2 files changed, 19 insertions(+), 38 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 5de825a..a019c5c 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -1,5 +1,5 @@ """ -Open Quantum Safe (OQS) Python Wrapper for liboqs +Open Quantum Safe (OQS) Python wrapper for liboqs The liboqs project provides post-quantum public key cryptography algorithms: https://github.com/open-quantum-safe/liboqs @@ -21,7 +21,19 @@ OQS_ERROR = -1 -def _load_shared_obj(name, already_installed_liboqs): +def _install_liboqs(directory): + os.system("cd " + directory) + os.system("git clone https://github.com/open-quantum-safe/liboqs --depth 1") + os.system("cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON") + os.system("cmake --build liboqs/build --parallel 4") + cmake_install_cmd = "cmake --build liboqs/build --target install" + if platform.system() == "Windows": + os.system(cmake_install_cmd) + else: + os.system("sudo " + cmake_install_cmd) + + +def _load_shared_obj(name, tried_installing_liboqs): """Attempts to load shared library.""" paths = [] @@ -42,53 +54,22 @@ def _load_shared_obj(name, already_installed_liboqs): lib = dll.LoadLibrary(path) return lib - if already_installed_liboqs: + if tried_installing_liboqs: raise RuntimeError("No " + name + " shared libraries found") # We don't have liboqs, so we try to install it - with tempfile.TemporaryDirectory() as tmpdirname: - oqs_install_str_UNIX = ( - "cd " - + tmpdirname - + """ - - git clone https://github.com/open-quantum-safe/liboqs --depth 1 - cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON - cmake --build liboqs/build --parallel 4 - sudo cmake --build liboqs/build --target install - """ - ) - - oqs_install_str_Windows = ( - "cd " - + tmpdirname - + """ - - git clone https://github.com/open-quantum-safe/liboqs --depth 1 - cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON - cmake --build liboqs/build --parallel 4 - cmake --build liboqs/build --target install - """ - ) - - oqs_install_str = ( - oqs_install_str_Windows - if platform.system() == "Windows" - else oqs_install_str_UNIX - ) - print("liboqs not found, downloading and installing liboqs in " + tmpdirname) print("This process may ask for your admin password.") input("Press ENTER to continue...") - os.system(oqs_install_str) + _install_liboqs(tmpdirname) print("Done installing liboqs") - return _load_shared_obj(name, already_installed_liboqs=True) + return _load_shared_obj(name, tried_installing_liboqs=True) try: - _liboqs = _load_shared_obj(name="oqs", already_installed_liboqs=False) + _liboqs = _load_shared_obj(name="oqs", tried_installing_liboqs=False) assert _liboqs except OSError as err: sys.exit("Could not load liboqs shared library") diff --git a/setup.py b/setup.py index e6f792d..9f20b3c 100644 --- a/setup.py +++ b/setup.py @@ -2,5 +2,5 @@ from distutils.core import setup setup( - packages=find_packages(exclude=('tests', 'docs', 'examples')), + packages=find_packages(exclude=("tests", "docs", "examples")), ) From e56e9547524c636970499b80fe7c1092bf9e2c5a Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Thu, 28 Mar 2024 10:38:37 -0400 Subject: [PATCH 11/27] Fix --- oqs/oqs.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index a019c5c..98b901a 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -22,15 +22,22 @@ def _install_liboqs(directory): - os.system("cd " + directory) - os.system("git clone https://github.com/open-quantum-safe/liboqs --depth 1") - os.system("cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON") - os.system("cmake --build liboqs/build --parallel 4") + oqs_install_str = ( + "cd " + + directory + + """ +git clone https://github.com/open-quantum-safe/liboqs --depth 1 +cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON +cmake --build liboqs/build --parallel 4 +""" + ) cmake_install_cmd = "cmake --build liboqs/build --target install" if platform.system() == "Windows": - os.system(cmake_install_cmd) + oqs_install_str += cmake_install_cmd else: - os.system("sudo " + cmake_install_cmd) + oqs_install_str += "sudo " + cmake_install_cmd + + os.system(oqs_install_str) def _load_shared_obj(name, tried_installing_liboqs): From d25b6b63834a141e910792a94f2de576b9d83627 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Thu, 28 Mar 2024 11:16:38 -0400 Subject: [PATCH 12/27] Finalized v0.10.0 --- README.md | 10 ++++++++++ oqs/oqs.py | 7 ++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0f207a6..fbce287 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,16 @@ by cmake -S liboqs -B liboqs/build -DCMAKE_INSTALL_PREFIX="C:\liboqs" -DBUILD_SHARED_LIBS=ON ``` +### Let liboqs-python install liboqs automatically (UNIX-like platforms) + +On UNIX-like platforms, if liboqs is not detected at runtime by liboqs-python, +it will be downloaded, configured and installed automatically (as a shared +library). This process will be performed only once, at runtime, i.e., when +loading the wrapper. The liboqs source directory will be automatically removed +at the end of the process. + +Note that Windows platforms are not (yet) supported. + ### Install and activate a Python virtual environment Execute in a Terminal/Console/Administrator Command Prompt diff --git a/oqs/oqs.py b/oqs/oqs.py index 98b901a..0b5536e 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -33,7 +33,9 @@ def _install_liboqs(directory): ) cmake_install_cmd = "cmake --build liboqs/build --target install" if platform.system() == "Windows": - oqs_install_str += cmake_install_cmd + raise RuntimeError( + "Automatic installation of liboqs is not (yet) supported on Windows" + ) else: oqs_install_str += "sudo " + cmake_install_cmd @@ -67,8 +69,7 @@ def _load_shared_obj(name, tried_installing_liboqs): # We don't have liboqs, so we try to install it with tempfile.TemporaryDirectory() as tmpdirname: print("liboqs not found, downloading and installing liboqs in " + tmpdirname) - print("This process may ask for your admin password.") - input("Press ENTER to continue...") + input("You may be asked for your admin password. Press ENTER to continue...") _install_liboqs(tmpdirname) print("Done installing liboqs") From 7dbbea9e06e5edecef27f1a6ac212565071bbbb9 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Thu, 28 Mar 2024 11:26:19 -0400 Subject: [PATCH 13/27] Removed Windows auto install --- oqs/oqs.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 0b5536e..8aab1a1 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -66,12 +66,17 @@ def _load_shared_obj(name, tried_installing_liboqs): if tried_installing_liboqs: raise RuntimeError("No " + name + " shared libraries found") - # We don't have liboqs, so we try to install it - with tempfile.TemporaryDirectory() as tmpdirname: - print("liboqs not found, downloading and installing liboqs in " + tmpdirname) - input("You may be asked for your admin password. Press ENTER to continue...") - _install_liboqs(tmpdirname) - print("Done installing liboqs") + # We don't have liboqs, so we try to install it (excludes Windows platforms) + if platform.system() != "Windows": + with tempfile.TemporaryDirectory() as tmpdirname: + print( + "liboqs not found, downloading and installing liboqs in " + tmpdirname + ) + input( + "You may be asked for your admin password. Press ENTER to continue..." + ) + _install_liboqs(tmpdirname) + print("Done installing liboqs") return _load_shared_obj(name, tried_installing_liboqs=True) From 279b6d92c1590133ca89b83fad5472dd24548111 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Thu, 28 Mar 2024 11:44:33 -0400 Subject: [PATCH 14/27] Code cleanup --- oqs/oqs.py | 69 +++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 8aab1a1..2e1335d 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -21,28 +21,7 @@ OQS_ERROR = -1 -def _install_liboqs(directory): - oqs_install_str = ( - "cd " - + directory - + """ -git clone https://github.com/open-quantum-safe/liboqs --depth 1 -cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON -cmake --build liboqs/build --parallel 4 -""" - ) - cmake_install_cmd = "cmake --build liboqs/build --target install" - if platform.system() == "Windows": - raise RuntimeError( - "Automatic installation of liboqs is not (yet) supported on Windows" - ) - else: - oqs_install_str += "sudo " + cmake_install_cmd - - os.system(oqs_install_str) - - -def _load_shared_obj(name, tried_installing_liboqs): +def _load_shared_obj(name): """Attempts to load shared library.""" paths = [] @@ -63,9 +42,34 @@ def _load_shared_obj(name, tried_installing_liboqs): lib = dll.LoadLibrary(path) return lib - if tried_installing_liboqs: - raise RuntimeError("No " + name + " shared libraries found") + raise RuntimeError("No " + name + " shared libraries found") + + +def _install_liboqs(directory): + """Attempts to install liboqs automatically.""" + oqs_install_str = ( + "cd " + + directory + + """ +git clone https://github.com/open-quantum-safe/liboqs --depth 1 +cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON +cmake --build liboqs/build --parallel 4 +""" + ) + cmake_install_cmd = "cmake --build liboqs/build --target install" + if platform.system() == "Windows": + raise RuntimeError( + "Automatic installation of liboqs is not (yet) supported on Windows" + ) + else: + oqs_install_str += "sudo " + cmake_install_cmd + os.system(oqs_install_str) + +try: + _liboqs = _load_shared_obj(name="oqs") + assert _liboqs +except RuntimeError: # We don't have liboqs, so we try to install it (excludes Windows platforms) if platform.system() != "Windows": with tempfile.TemporaryDirectory() as tmpdirname: @@ -77,17 +81,12 @@ def _load_shared_obj(name, tried_installing_liboqs): ) _install_liboqs(tmpdirname) print("Done installing liboqs") - - return _load_shared_obj(name, tried_installing_liboqs=True) - - -try: - _liboqs = _load_shared_obj(name="oqs", tried_installing_liboqs=False) - assert _liboqs -except OSError as err: - sys.exit("Could not load liboqs shared library") -except RuntimeError as err: - sys.exit("No liboqs shared libraries found") + # Try loading it again + try: + _liboqs = _load_shared_obj(name="oqs") + assert _liboqs + except RuntimeError: + sys.exit("Could not load liboqs shared library") def native(): From c115be1c4419d3e5088da449df979b7cbb902988 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 20:36:52 -0400 Subject: [PATCH 15/27] Win auto install (#81) Fix Windows auto install, refactoring --- .github/workflows/python.yml | 29 ++------- README.md | 38 ++++++------ oqs/oqs.py | 111 +++++++++++++++++++++++------------ 3 files changed, 94 insertions(+), 84 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index fd7d8dc..c4483d3 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -2,25 +2,23 @@ name: GitHub actions on: push: - branches: [ "**" ] + branches: ["**"] pull_request: - branches: [ "**" ] + branches: ["**"] repository_dispatch: - types: [ "**" ] + types: ["**"] permissions: contents: read env: BUILD_TYPE: Debug - LD_LIBRARY_PATH: /usr/local/lib - WIN_LIBOQS_INSTALL_PATH: C:\liboqs jobs: build: strategy: matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] + os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: @@ -36,14 +34,6 @@ jobs: python -m pip install --upgrade pip pip install nose2 - - name: Install liboqs POSIX - if: matrix.os != 'windows-latest' - run: | - git clone --branch main --single-branch --depth 1 https://github.com/open-quantum-safe/liboqs - cmake -S liboqs -B liboqs/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_SHARED_LIBS=ON -DOQS_BUILD_ONLY_LIB=ON - cmake --build liboqs/build --parallel 4 - sudo cmake --build liboqs/build --target install - - name: Run examples POSIX if: matrix.os != 'windows-latest' run: | @@ -59,20 +49,10 @@ jobs: run: | nose2 --verbose - - name: Install liboqs Windows - if: matrix.os == 'windows-latest' - shell: cmd - run: | - git clone --branch main --single-branch --depth 1 https://github.com/open-quantum-safe/liboqs - cmake -S liboqs -B liboqs\build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{env.WIN_LIBOQS_INSTALL_PATH}} -DBUILD_SHARED_LIBS=ON -DOQS_BUILD_ONLY_LIB=ON - cmake --build liboqs\build --parallel 4 - cmake --build liboqs\build --target install - - name: Run examples Windows if: matrix.os == 'windows-latest' shell: cmd run: | - set PATH=%PATH%;${{env.WIN_LIBOQS_INSTALL_PATH}}\bin pip install . python examples/kem.py echo. @@ -84,5 +64,4 @@ jobs: shell: cmd if: matrix.os == 'windows-latest' run: | - set PATH=%PATH%;${{env.WIN_LIBOQS_INSTALL_PATH}}\bin nose2 --verbose diff --git a/README.md b/README.md index fbce287..528352d 100644 --- a/README.md +++ b/README.md @@ -65,32 +65,30 @@ liboqs' library directory, e.g., export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib ``` -On Windows platforms, **you must ensure** that the liboqs shared library -`oqs.dll` is visible system-wide, and that the following environment variable -are being set. Use the "Edit the system environment variables" Control Panel -tool or execute in a Command Prompt, e.g., +On Windows platforms, **you must ensure** that you add the +`-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE` flag to CMake, and that the liboqs +shared library `oqs.dll` is visible system-wide, i.e., set the `PATH` +environment variable accordingly by using the "Edit the system environment +variables" Control Panel tool or executing in a Command Prompt ```shell set PATH=%PATH%;C:\Program Files (x86)\liboqs\bin ``` You can change liboqs' installation directory by configuring the build to use -an alternative path, e.g., `C:\liboqs`, by replacing the first CMake line above -by +an alternative path, e.g., `C:\liboqs`, by passing the +`-DCMAKE_INSTALL_PREFIX=/path/to/liboqs` flag to CMake, e.g., ```shell cmake -S liboqs -B liboqs/build -DCMAKE_INSTALL_PREFIX="C:\liboqs" -DBUILD_SHARED_LIBS=ON ``` -### Let liboqs-python install liboqs automatically (UNIX-like platforms) - -On UNIX-like platforms, if liboqs is not detected at runtime by liboqs-python, -it will be downloaded, configured and installed automatically (as a shared -library). This process will be performed only once, at runtime, i.e., when -loading the wrapper. The liboqs source directory will be automatically removed -at the end of the process. +### Let liboqs-python install liboqs automatically -Note that Windows platforms are not (yet) supported. +If liboqs is not detected at runtime by liboqs-python, it will be downloaded, +configured and installed automatically (as a shared library). This process will +be performed only once, at runtime, i.e., when loading the wrapper. The liboqs +source directory will be automatically removed at the end of the process. ### Install and activate a Python virtual environment @@ -153,12 +151,12 @@ import oqs ``` liboqs-python defines two main classes: `KeyEncapsulation` and `Signature`, -providing post-quantum key encapsulation and signture mechanisms, respectively. -Each must be instantiated with a string identifying one of mechanisms supported -by liboqs; these can be enumerated using the `get_enabled_KEM_mechanisms()` and -`get_enabled_sig_mechanisms()` functions. The files in `examples/` demonstrate -the wrapper's API. Support for alternative RNGs is provided via the -`randombytes_*()` functions. +providing post-quantum key encapsulation and signature mechanisms, +respectively. Each must be instantiated with a string identifying one of +mechanisms supported by liboqs; these can be enumerated using the +`get_enabled_KEM_mechanisms()` and `get_enabled_sig_mechanisms()` functions. +The files in `examples/` demonstrate the wrapper's API. Support for alternative +RNGs is provided via the `randombytes_*()` functions. The liboqs-python project should be in the `PYTHONPATH`. To ensure this on UNIX-like systems, execute diff --git a/oqs/oqs.py b/oqs/oqs.py index 2e1335d..47fcde1 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -14,76 +14,109 @@ import platform # to learn the OS we're on import sys import tempfile # to install liboqs on demand +import time import warnings +# liboqs-python tries to automatically install and load this liboqs version in +# case no other version is found +OQS_VERSION = "0.10.0" + # Expected return value from native OQS functions OQS_SUCCESS = 0 OQS_ERROR = -1 -def _load_shared_obj(name): +def _countdown(seconds): + while seconds > 0: + print(seconds, end=" ") + sys.stdout.flush() + seconds -= 1 + time.sleep(1) + print() + + +def _load_shared_obj(name, additional_searching_paths=None): """Attempts to load shared library.""" paths = [] + # Search additional path, if any + if additional_searching_paths: + for path in additional_searching_paths: + if platform.system() == "Darwin": + paths.append( + os.path.abspath(path) + os.path.sep + "lib" + name + ".dylib" + ) + if platform.system() == "Linux": + paths.append(os.path.abspath(path) + os.path.sep + "lib" + name + ".so") + # https://stackoverflow.com/questions/856116/changing-ld-library-path-at-runtime-for-ctypes + # os.environ["LD_LIBRARY_PATH"] += os.path.abspath(path) + if platform.system() == "Windows": + paths.append(os.path.abspath(path) + os.path.sep + name + ".dll") + # Does not work + # os.environ["PATH"] += os.path.abspath(path) + # Search typical locations try: - paths += [ctu.find_library(name)] + paths.insert(0, ctu.find_library(name)) except FileNotFoundError: pass try: - paths += [ctu.find_library("lib" + name)] + paths.insert(0, ctu.find_library("lib" + name)) except FileNotFoundError: pass dll = ct.windll if platform.system() == "Windows" else ct.cdll + # for elem in paths: + # print(elem) + for path in paths: if path: - lib = dll.LoadLibrary(path) - return lib + try: + lib = dll.LoadLibrary(path) + return lib + except OSError: + pass raise RuntimeError("No " + name + " shared libraries found") -def _install_liboqs(directory): - """Attempts to install liboqs automatically.""" - oqs_install_str = ( - "cd " - + directory - + """ -git clone https://github.com/open-quantum-safe/liboqs --depth 1 -cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON -cmake --build liboqs/build --parallel 4 -""" - ) - cmake_install_cmd = "cmake --build liboqs/build --target install" - if platform.system() == "Windows": - raise RuntimeError( - "Automatic installation of liboqs is not (yet) supported on Windows" +def _install_liboqs(directory, oqs_version): + """Install liboqs in $HOME/directory.""" + with tempfile.TemporaryDirectory() as tmpdirname: + oqs_install_str = ( + "cd " + + tmpdirname + + " && git clone https://github.com/open-quantum-safe/liboqs --branch " + + oqs_version + + " --depth 1 && cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=" + + directory ) - else: - oqs_install_str += "sudo " + cmake_install_cmd - os.system(oqs_install_str) - - + if platform.system() == "Windows": + oqs_install_str += " -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE" + oqs_install_str += " && cmake --build liboqs/build --parallel 4 && cmake --build liboqs/build --target install" + print("liboqs not found, installing it in " + directory) + _countdown(5) + os.system(oqs_install_str) + print("Done installing liboqs") + + +home_dir = os.path.expanduser("~") +oqs_install_dir = os.path.abspath(home_dir + os.path.sep + "oqs") # $HOME/oqs +oqs_lib_dir = ( + os.path.abspath(oqs_install_dir + os.path.sep + "bin") # $HOME/oqs/bin + if platform.system() == "Windows" + else os.path.abspath(oqs_install_dir + os.path.sep + "lib") # $HOME/oqs/lib +) try: - _liboqs = _load_shared_obj(name="oqs") + _liboqs = _load_shared_obj(name="oqs", additional_searching_paths=[oqs_lib_dir]) assert _liboqs except RuntimeError: - # We don't have liboqs, so we try to install it (excludes Windows platforms) - if platform.system() != "Windows": - with tempfile.TemporaryDirectory() as tmpdirname: - print( - "liboqs not found, downloading and installing liboqs in " + tmpdirname - ) - input( - "You may be asked for your admin password. Press ENTER to continue..." - ) - _install_liboqs(tmpdirname) - print("Done installing liboqs") + # We don't have liboqs, so we try to install it automatically + _install_liboqs(directory=oqs_install_dir, oqs_version=OQS_VERSION) # Try loading it again try: - _liboqs = _load_shared_obj(name="oqs") + _liboqs = _load_shared_obj(name="oqs", additional_searching_paths=[oqs_lib_dir]) assert _liboqs except RuntimeError: sys.exit("Could not load liboqs shared library") @@ -114,7 +147,7 @@ def oqs_python_version(): return result -# Warn the use if the liboqs version differs from liboqs-python version +# Warn the user if the liboqs version differs from liboqs-python version if oqs_version() != oqs_python_version(): warnings.warn( "liboqs version {} differs from liboqs-python version {}".format( From 1c0ec3ef837c2222ab0a7a41eb5ba48cf7c8af43 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 20:47:41 -0400 Subject: [PATCH 16/27] Finalizing 0.10.0 --- oqs/oqs.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 47fcde1..efd8c94 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -38,6 +38,7 @@ def _countdown(seconds): def _load_shared_obj(name, additional_searching_paths=None): """Attempts to load shared library.""" paths = [] + dll = ct.windll if platform.system() == "Windows" else ct.cdll # Search additional path, if any if additional_searching_paths: @@ -65,11 +66,6 @@ def _load_shared_obj(name, additional_searching_paths=None): except FileNotFoundError: pass - dll = ct.windll if platform.system() == "Windows" else ct.cdll - - # for elem in paths: - # print(elem) - for path in paths: if path: try: @@ -81,8 +77,8 @@ def _load_shared_obj(name, additional_searching_paths=None): raise RuntimeError("No " + name + " shared libraries found") -def _install_liboqs(directory, oqs_version): - """Install liboqs in $HOME/directory.""" +def _install_liboqs(target_directory, oqs_version): + """Install liboqs version oqs_version in the target_directory.""" with tempfile.TemporaryDirectory() as tmpdirname: oqs_install_str = ( "cd " @@ -90,30 +86,30 @@ def _install_liboqs(directory, oqs_version): + " && git clone https://github.com/open-quantum-safe/liboqs --branch " + oqs_version + " --depth 1 && cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=" - + directory + + target_directory ) if platform.system() == "Windows": oqs_install_str += " -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE" oqs_install_str += " && cmake --build liboqs/build --parallel 4 && cmake --build liboqs/build --target install" - print("liboqs not found, installing it in " + directory) + print("liboqs not found, installing it in " + target_directory) _countdown(5) os.system(oqs_install_str) print("Done installing liboqs") home_dir = os.path.expanduser("~") -oqs_install_dir = os.path.abspath(home_dir + os.path.sep + "oqs") # $HOME/oqs +oqs_install_dir = os.path.abspath(home_dir + os.path.sep + "_oqs") # $HOME/_oqs oqs_lib_dir = ( - os.path.abspath(oqs_install_dir + os.path.sep + "bin") # $HOME/oqs/bin + os.path.abspath(oqs_install_dir + os.path.sep + "bin") # $HOME/_oqs/bin if platform.system() == "Windows" - else os.path.abspath(oqs_install_dir + os.path.sep + "lib") # $HOME/oqs/lib + else os.path.abspath(oqs_install_dir + os.path.sep + "lib") # $HOME/_oqs/lib ) try: _liboqs = _load_shared_obj(name="oqs", additional_searching_paths=[oqs_lib_dir]) assert _liboqs except RuntimeError: # We don't have liboqs, so we try to install it automatically - _install_liboqs(directory=oqs_install_dir, oqs_version=OQS_VERSION) + _install_liboqs(target_directory=oqs_install_dir, oqs_version=OQS_VERSION) # Try loading it again try: _liboqs = _load_shared_obj(name="oqs", additional_searching_paths=[oqs_lib_dir]) From 14e0c163dcbe9e253134716ace8ad2f4df83e2be Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 20:53:19 -0400 Subject: [PATCH 17/27] Updated README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 528352d..2412576 100644 --- a/README.md +++ b/README.md @@ -85,10 +85,15 @@ cmake -S liboqs -B liboqs/build -DCMAKE_INSTALL_PREFIX="C:\liboqs" -DBUILD_SHARE ### Let liboqs-python install liboqs automatically -If liboqs is not detected at runtime by liboqs-python, it will be downloaded, +If you want to avoid installing liboqs manually (as detailed in the step +above), then you can let the liboqs-python wrapper try to install it for you +automatically, as follows. + +When liboqs is not detected at runtime by liboqs-python, it will be downloaded, configured and installed automatically (as a shared library). This process will -be performed only once, at runtime, i.e., when loading the wrapper. The liboqs -source directory will be automatically removed at the end of the process. +be performed only once, at runtime, i.e., when loading the liboqs-python +wrapper. The liboqs source directory will be automatically removed at the end +of the process. ### Install and activate a Python virtual environment From f040d11aa6f5dea388b8b3f7868337c9741eeaa8 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 20:54:45 -0400 Subject: [PATCH 18/27] Finalized 0.10.0 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2412576..2a93ff9 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ cmake -S liboqs -B liboqs/build -DCMAKE_INSTALL_PREFIX="C:\liboqs" -DBUILD_SHARE ### Let liboqs-python install liboqs automatically If you want to avoid installing liboqs manually (as detailed in the step -above), then you can let the liboqs-python wrapper try to install it for you -automatically, as follows. +above), then you can skip the step above and let the liboqs-python wrapper try +to install it for you automatically, as follows. When liboqs is not detected at runtime by liboqs-python, it will be downloaded, configured and installed automatically (as a shared library). This process will From f78a75a2a454bb9d595cec582d117b1aec2ad593 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:00:16 -0400 Subject: [PATCH 19/27] Minor fix --- oqs/oqs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index efd8c94..f3e1703 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -47,14 +47,14 @@ def _load_shared_obj(name, additional_searching_paths=None): paths.append( os.path.abspath(path) + os.path.sep + "lib" + name + ".dylib" ) - if platform.system() == "Linux": - paths.append(os.path.abspath(path) + os.path.sep + "lib" + name + ".so") - # https://stackoverflow.com/questions/856116/changing-ld-library-path-at-runtime-for-ctypes - # os.environ["LD_LIBRARY_PATH"] += os.path.abspath(path) - if platform.system() == "Windows": + elif platform.system() == "Windows": paths.append(os.path.abspath(path) + os.path.sep + name + ".dll") # Does not work # os.environ["PATH"] += os.path.abspath(path) + else: # Linux/FreeBSD/UNIX-like + paths.append(os.path.abspath(path) + os.path.sep + "lib" + name + ".so") + # https://stackoverflow.com/questions/856116/changing-ld-library-path-at-runtime-for-ctypes + # os.environ["LD_LIBRARY_PATH"] += os.path.abspath(path) # Search typical locations try: From 3dbf193da6c33bcc688d20f0bfb6276c0022f00e Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:02:37 -0400 Subject: [PATCH 20/27] Finalized 0.10.0 --- oqs/oqs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index f3e1703..5b25f2b 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -51,7 +51,7 @@ def _load_shared_obj(name, additional_searching_paths=None): paths.append(os.path.abspath(path) + os.path.sep + name + ".dll") # Does not work # os.environ["PATH"] += os.path.abspath(path) - else: # Linux/FreeBSD/UNIX-like + else: # Linux/FreeBSD/UNIX paths.append(os.path.abspath(path) + os.path.sep + "lib" + name + ".so") # https://stackoverflow.com/questions/856116/changing-ld-library-path-at-runtime-for-ctypes # os.environ["LD_LIBRARY_PATH"] += os.path.abspath(path) From 1aa5c08a33a5d8d68a57b7693a0c618f61775dee Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:08:07 -0400 Subject: [PATCH 21/27] More flexibility --- oqs/oqs.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 5b25f2b..81d8447 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -77,15 +77,18 @@ def _load_shared_obj(name, additional_searching_paths=None): raise RuntimeError("No " + name + " shared libraries found") -def _install_liboqs(target_directory, oqs_version): - """Install liboqs version oqs_version in the target_directory.""" +def _install_liboqs(target_directory, oqs_version=None): + """Install liboqs version oqs_version (if None, installs latest at HEAD) in the target_directory.""" with tempfile.TemporaryDirectory() as tmpdirname: oqs_install_str = ( "cd " + tmpdirname - + " && git clone https://github.com/open-quantum-safe/liboqs --branch " - + oqs_version - + " --depth 1 && cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=" + + " && git clone https://github.com/open-quantum-safe/liboqs" + ) + if oqs_version: + oqs_install_str += " --branch " + oqs_version + oqs_install_str += ( + " --depth 1 && cmake -S liboqs -B liboqs/build -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=" + target_directory ) if platform.system() == "Windows": From dce74bd600d10dde42e1a39e05a88dd960007f3b Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:15:12 -0400 Subject: [PATCH 22/27] Final 0.10.0 --- oqs/oqs.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 81d8447..1def550 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -17,13 +17,20 @@ import time import warnings + +def oqs_python_version(): + """liboqs-python version string.""" + try: + result = importlib.metadata.version("liboqs-python") + except importlib.metadata.PackageNotFoundError: + warnings.warn("Please install liboqs-python using pip install") + return None + return result + + # liboqs-python tries to automatically install and load this liboqs version in # case no other version is found -OQS_VERSION = "0.10.0" - -# Expected return value from native OQS functions -OQS_SUCCESS = 0 -OQS_ERROR = -1 +OQS_VERSION = oqs_python_version() def _countdown(seconds): @@ -121,6 +128,11 @@ def _install_liboqs(target_directory, oqs_version=None): sys.exit("Could not load liboqs shared library") +# Expected return value from native OQS functions +OQS_SUCCESS = 0 +OQS_ERROR = -1 + + def native(): """Handle to native liboqs handler.""" return _liboqs @@ -136,16 +148,6 @@ def oqs_version(): return ct.c_char_p(native().OQS_version()).value.decode("UTF-8") -def oqs_python_version(): - """liboqs-python version string.""" - try: - result = importlib.metadata.version("liboqs-python") - except importlib.metadata.PackageNotFoundError: - warnings.warn("Please install liboqs-python using pip install") - return None - return result - - # Warn the user if the liboqs version differs from liboqs-python version if oqs_version() != oqs_python_version(): warnings.warn( From 23f0a69ed3aa8544a72b0e15362fb23b1c8aa057 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:21:33 -0400 Subject: [PATCH 23/27] Simplified GitHub action --- .github/workflows/python.yml | 21 ++++++++++++++++ .github/workflows/python_auto.yml | 41 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 .github/workflows/python_auto.yml diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index c4483d3..053d139 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -13,6 +13,8 @@ permissions: env: BUILD_TYPE: Debug + LD_LIBRARY_PATH: /usr/local/lib + WIN_LIBOQS_INSTALL_PATH: C:\liboqs jobs: build: @@ -34,6 +36,14 @@ jobs: python -m pip install --upgrade pip pip install nose2 + - name: Install liboqs POSIX + if: matrix.os != 'windows-latest' + run: | + git clone --branch main --single-branch --depth 1 https://github.com/open-quantum-safe/liboqs + cmake -S liboqs -B liboqs/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_SHARED_LIBS=ON -DOQS_BUILD_ONLY_LIB=ON + cmake --build liboqs/build --parallel 4 + sudo cmake --build liboqs/build --target install + - name: Run examples POSIX if: matrix.os != 'windows-latest' run: | @@ -49,10 +59,20 @@ jobs: run: | nose2 --verbose + - name: Install liboqs Windows + if: matrix.os == 'windows-latest' + shell: cmd + run: | + git clone --branch main --single-branch --depth 1 https://github.com/open-quantum-safe/liboqs + cmake -S liboqs -B liboqs\build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{env.WIN_LIBOQS_INSTALL_PATH}} -DBUILD_SHARED_LIBS=ON -DOQS_BUILD_ONLY_LIB=ON + cmake --build liboqs\build --parallel 4 + cmake --build liboqs\build --target install + - name: Run examples Windows if: matrix.os == 'windows-latest' shell: cmd run: | + set PATH=%PATH%;${{env.WIN_LIBOQS_INSTALL_PATH}}\bin pip install . python examples/kem.py echo. @@ -64,4 +84,5 @@ jobs: shell: cmd if: matrix.os == 'windows-latest' run: | + set PATH=%PATH%;${{env.WIN_LIBOQS_INSTALL_PATH}}\bin nose2 --verbose diff --git a/.github/workflows/python_auto.yml b/.github/workflows/python_auto.yml new file mode 100644 index 0000000..641f460 --- /dev/null +++ b/.github/workflows/python_auto.yml @@ -0,0 +1,41 @@ +name: GitHub actions + +on: + push: + branches: ["**"] + pull_request: + branches: ["**"] + repository_dispatch: + types: ["**"] + +permissions: + contents: read + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + + - name: Run examples + run: | + python -m pip install --upgrade pip + pip install . + python examples/kem.py + echo + python examples/sig.py + echo + python examples/rand.py + + - name: Run unit tests + run: | + nose2 --verbose From 50a6174bfa99ed6395d7f2f7b8af32b37dac6eff Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:26:00 -0400 Subject: [PATCH 24/27] Finalized 0.10.0 --- .github/workflows/{python.yml => python_detailed.yml} | 2 +- .github/workflows/{python_auto.yml => python_simplified.yml} | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename .github/workflows/{python.yml => python_detailed.yml} (98%) rename .github/workflows/{python_auto.yml => python_simplified.yml} (95%) diff --git a/.github/workflows/python.yml b/.github/workflows/python_detailed.yml similarity index 98% rename from .github/workflows/python.yml rename to .github/workflows/python_detailed.yml index 053d139..418faae 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python_detailed.yml @@ -1,4 +1,4 @@ -name: GitHub actions +name: GitHub actions detailed on: push: diff --git a/.github/workflows/python_auto.yml b/.github/workflows/python_simplified.yml similarity index 95% rename from .github/workflows/python_auto.yml rename to .github/workflows/python_simplified.yml index 641f460..d503f07 100644 --- a/.github/workflows/python_auto.yml +++ b/.github/workflows/python_simplified.yml @@ -1,4 +1,4 @@ -name: GitHub actions +name: GitHub actions simplified on: push: diff --git a/README.md b/README.md index 2a93ff9..b1fb632 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # liboqs-python: Python 3 bindings for liboqs -[![GitHub actions](https://github.com/open-quantum-safe/liboqs-python/actions/workflows/python.yml/badge.svg)](https://github.com/open-quantum-safe/liboqs-python/actions) +[![GitHub actions](https://github.com/open-quantum-safe/liboqs-python/actions/workflows/python_simplified.yml/badge.svg)](https://github.com/open-quantum-safe/liboqs-python/actions) --- From 7b0c84d165701e9916fc85ad96973ab93b516ab3 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 21:27:04 -0400 Subject: [PATCH 25/27] Fix --- .github/workflows/python_simplified.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/python_simplified.yml b/.github/workflows/python_simplified.yml index d503f07..387ce6e 100644 --- a/.github/workflows/python_simplified.yml +++ b/.github/workflows/python_simplified.yml @@ -31,9 +31,7 @@ jobs: python -m pip install --upgrade pip pip install . python examples/kem.py - echo python examples/sig.py - echo python examples/rand.py - name: Run unit tests From 76e878a10166060d86146d0c55823bca3a792802 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sat, 30 Mar 2024 22:28:24 -0400 Subject: [PATCH 26/27] Finalized 0.10.0 --- oqs/oqs.py | 38 +++++++++++++++++++++++--------------- setup.py | 7 ++++--- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 1def550..0e92d63 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -107,25 +107,33 @@ def _install_liboqs(target_directory, oqs_version=None): print("Done installing liboqs") -home_dir = os.path.expanduser("~") -oqs_install_dir = os.path.abspath(home_dir + os.path.sep + "_oqs") # $HOME/_oqs -oqs_lib_dir = ( - os.path.abspath(oqs_install_dir + os.path.sep + "bin") # $HOME/_oqs/bin - if platform.system() == "Windows" - else os.path.abspath(oqs_install_dir + os.path.sep + "lib") # $HOME/_oqs/lib -) -try: - _liboqs = _load_shared_obj(name="oqs", additional_searching_paths=[oqs_lib_dir]) - assert _liboqs -except RuntimeError: - # We don't have liboqs, so we try to install it automatically - _install_liboqs(target_directory=oqs_install_dir, oqs_version=OQS_VERSION) - # Try loading it again +def _load_liboqs(): + home_dir = os.path.expanduser("~") + oqs_install_dir = os.path.abspath(home_dir + os.path.sep + "_oqs") # $HOME/_oqs + oqs_lib_dir = ( + os.path.abspath(oqs_install_dir + os.path.sep + "bin") # $HOME/_oqs/bin + if platform.system() == "Windows" + else os.path.abspath(oqs_install_dir + os.path.sep + "lib") # $HOME/_oqs/lib + ) try: _liboqs = _load_shared_obj(name="oqs", additional_searching_paths=[oqs_lib_dir]) assert _liboqs except RuntimeError: - sys.exit("Could not load liboqs shared library") + # We don't have liboqs, so we try to install it automatically + _install_liboqs(target_directory=oqs_install_dir, oqs_version=OQS_VERSION) + # Try loading it again + try: + _liboqs = _load_shared_obj( + name="oqs", additional_searching_paths=[oqs_lib_dir] + ) + assert _liboqs + except RuntimeError: + sys.exit("Could not load liboqs shared library") + + return _liboqs + + +_liboqs = _load_liboqs() # Expected return value from native OQS functions diff --git a/setup.py b/setup.py index 9f20b3c..ab322e4 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ -from setuptools import find_packages -from distutils.core import setup +from setuptools import find_packages, setup setup( - packages=find_packages(exclude=("tests", "docs", "examples")), + packages=find_packages( + exclude=["tests", "docs", "examples"], + ), ) From 707f469cbd520dd255ba08036757b5bfd308e1f2 Mon Sep 17 00:00:00 2001 From: Vlad Gheorghiu Date: Sun, 31 Mar 2024 12:47:38 -0400 Subject: [PATCH 27/27] Final 0.10.0 --- oqs/oqs.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/oqs/oqs.py b/oqs/oqs.py index 0e92d63..4f67184 100644 --- a/oqs/oqs.py +++ b/oqs/oqs.py @@ -30,7 +30,7 @@ def oqs_python_version(): # liboqs-python tries to automatically install and load this liboqs version in # case no other version is found -OQS_VERSION = oqs_python_version() +REQUIRE_OQS_VERSION = oqs_python_version() def _countdown(seconds): @@ -120,7 +120,9 @@ def _load_liboqs(): assert _liboqs except RuntimeError: # We don't have liboqs, so we try to install it automatically - _install_liboqs(target_directory=oqs_install_dir, oqs_version=OQS_VERSION) + _install_liboqs( + target_directory=oqs_install_dir, oqs_version=REQUIRE_OQS_VERSION + ) # Try loading it again try: _liboqs = _load_shared_obj(