Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-libnacl for openSUSE:Factory checked in at 2024-03-01 23:36:34 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-libnacl (Old) and /work/SRC/openSUSE:Factory/.python-libnacl.new.1770 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-libnacl" Fri Mar 1 23:36:34 2024 rev:23 rq:1153722 version:2.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-libnacl/python-libnacl.changes 2023-07-05 15:31:47.855006819 +0200 +++ /work/SRC/openSUSE:Factory/.python-libnacl.new.1770/python-libnacl.changes 2024-03-01 23:36:53.416246816 +0100 @@ -1,0 +2,10 @@ +Fri Mar 1 03:20:14 UTC 2024 - Steve Kowalik <steven.kowa...@suse.com> + +- Update to 2.1.0: + * Added classes to the libnacl.aead module allowing for the use of + XChaCha20-Poly1305-IETF, ChaCha20-Poly1305-IETF, and AES256-GCM. + * Added the libnacl.kx module. This module contains the ExchangeKey class. +- Switch to autosetup and pyproject macros. +- Drop patch crypto_kdf_derive.patch, no longer required. + +------------------------------------------------------------------- Old: ---- crypto_kdf_derive.patch libnacl-1.7.2.tar.gz New: ---- libnacl-2.1.0.tar.gz BETA DEBUG BEGIN: Old:- Switch to autosetup and pyproject macros. - Drop patch crypto_kdf_derive.patch, no longer required. BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-libnacl.spec ++++++ --- /var/tmp/diff_new_pack.3B180q/_old 2024-03-01 23:36:53.952266200 +0100 +++ /var/tmp/diff_new_pack.3B180q/_new 2024-03-01 23:36:53.952266200 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-libnacl # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,15 +18,16 @@ %{?sle15_python_module_pythons} Name: python-libnacl -Version: 1.7.2 +Version: 2.1.0 Release: 0 Summary: Python bindings for libsodium based on ctypes License: Apache-2.0 URL: https://github.com/saltstack/libnacl Source0: https://github.com/saltstack/libnacl/archive/v%{version}.tar.gz#/libnacl-%{version}.tar.gz -Patch0: crypto_kdf_derive.patch BuildRequires: %{python_module devel} -BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module pip} +BuildRequires: %{python_module poetry} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: pkgconfig BuildRequires: python-rpm-macros @@ -34,6 +35,7 @@ # This will need updating and verification but smart magic is not copied by # singlespec macros Requires: libsodium23 +BuildArch: noarch %python_subpackages %description @@ -42,14 +44,13 @@ in libnacl/__init__.py can be pulled out and placed directly in any project to give a single file binding to all of nacl. %prep -%setup -q -n libnacl-%{version} -%patch0 -p1 +%autosetup -p1 -n libnacl-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}/%{$python_sitelib} %check @@ -58,5 +59,6 @@ %files %{python_files} %license LICENSE %doc README.rst -%{python_sitelib}/* +%{python_sitelib}/libnacl +%{python_sitelib}/libnacl-%{version}.dist-info ++++++ libnacl-1.7.2.tar.gz -> libnacl-2.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/.readthedocs.yaml new/libnacl-2.1.0/.readthedocs.yaml --- old/libnacl-1.7.2/.readthedocs.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/.readthedocs.yaml 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,23 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: doc/conf.py + +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +# python: +# install: +# - requirements: docs/requirements.txt + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/AUTHORS new/libnacl-2.1.0/AUTHORS --- old/libnacl-1.7.2/AUTHORS 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/AUTHORS 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -Thomas S Hatch -Sam Smith -Pedro Algarvio diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/LICENSE new/libnacl-2.1.0/LICENSE --- old/libnacl-1.7.2/LICENSE 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/LICENSE 2023-08-06 23:22:51.000000000 +0200 @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {2014} Thomas S Hatch + Copyright {2023} Thomas S Hatch Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/MANIFEST.in new/libnacl-2.1.0/MANIFEST.in --- old/libnacl-1.7.2/MANIFEST.in 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/MANIFEST.in 2023-08-06 23:22:51.000000000 +0200 @@ -1,5 +1,4 @@ include LICENSE -include AUTHORS include README.rst recursive-include tests *.py recursive-include doc * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/conf.py new/libnacl-2.1.0/doc/conf.py --- old/libnacl-1.7.2/doc/conf.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/conf.py 2023-08-06 23:22:51.000000000 +0200 @@ -15,7 +15,6 @@ import sys import os sys.path.insert(0, os.path.abspath('..')) -from libnacl import version # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -48,7 +47,7 @@ # General information about the project. project = u'libnacl' -copyright = u'2020, Thomas S Hatch' +copyright = u'2023, Thomas S Hatch' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -56,8 +55,8 @@ # # The short X.Y version. # The full version, including alpha/beta/rc tags. -release = version - +release = "2.1.0" +version = release # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None @@ -267,7 +266,7 @@ epub_title = u'libnacl' epub_author = u'Thomas S Hatch' epub_publisher = u'Thomas S Hatch' -epub_copyright = u'2020, Thomas S Hatch' +epub_copyright = u'2023, Thomas S Hatch' # The basename for the epub file. It defaults to the project name. #epub_basename = u'libnacl' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/index.rst new/libnacl-2.1.0/doc/index.rst --- old/libnacl-1.7.2/doc/index.rst 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/index.rst 2023-08-06 23:22:51.000000000 +0200 @@ -11,6 +11,7 @@ topics/secret topics/sign topics/dual + topics/aead topics/utils topics/raw_public topics/raw_sealed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/aead.rst new/libnacl-2.1.0/doc/topics/aead.rst --- old/libnacl-1.7.2/doc/topics/aead.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/aead.rst 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,33 @@ +============================================= +Authenticated Encryption with Associated Data +============================================= + +One of the most powerful symmetric encryption models available i s known as AEAD. +The libsodium library enables four models of AEAD encryption. As of libnacl 2.0 +we expose 3 of them. + +Using AEAD with libnacl is very easy and can be executed following the same models +as the rest of libnacl. + +The recommended algorithm to use is `XChaCha20-Poly1305-IETF`. Some organizations +require the use of AES, in these cases please use AESGCM. + +For more information on AEAD please see the libsodium documentation + +Using the AEAD system is very easy. + +.. code-block:: python + + import libnacl.aead + + msg = b"Our King? Well i didn't vote for you!!" + aad = b'\x00\x11\x22\x33' + box = libnacl.aead.AEAD_XCHACHA() + ctxt = box.encrypt(msg, aad) + + box2 = libnacl.aead.AEAD_XCHACHA(box.sk) + clear1 = box.decrypt(ctxt, len(aad)) + + ctxt2 = box2.encrypt(msg, aad) + clear3 = box.decrypt(ctxt2, len(aad)) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/kx.rst new/libnacl-2.1.0/doc/topics/kx.rst --- old/libnacl-1.7.2/doc/topics/kx.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/kx.rst 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,38 @@ +======================= +Key Exchange Encryption +======================= + +The X25519 key exchange algorithm in libsodium allows for key exchange encryption +to be safely executed. The ExchangeKey class makes it easy to use key exchange wrapping +AEAD encryption. This class works similarly to sealed boxes, but offers more functionality +and better security. + +When using the ExchangeKey encryption class you can select which AEAD encryption +subsystem to use, but it is recommended to stick with the default XChaCha algorithm. +The options are: `aesgcm` for the AES256-GCM construct, `xchacha` for the XChaCha20-Poly1305-IETF +construct, and `chacha` for the ChaCha20-Poly1305-IETF construct. + +To use the ExchangeKey system, simply create an ExchangeKey class for `bob` and `alice` +and then encrypt a message and additional unencrypted data and send them back and forth. + +In this example, bob acts as the client, and alice acts as the server. The underlying +nature of the connections are irrelevant, just that once end needs to call the server +functions and the other needs to call the client functions. + +.. code-block:: python + + # Import libnacl libs + import libnacl.kx + + msg = b'You\'ve got two empty halves of coconut and you\'re bangin\' \'em together.' + aad = b'A Duck!' + # Make Bob and Alice Exchange Keys + bob = libnacl.kx.ExchangeKey() + alice = libnacl.kx.ExchangeKey() + # Encrypt with bob as client and alice as server + bob_ctxt = bob.encrypt_client(alice.kx_pk, msg, aad) + bclear, clear_aad = alice.decrypt_server(bob.kx_pk, bob_ctxt, len(aad)) + # Similarly you can have alice encrypt as server and bob decrypt as client + alice_ctxt = alice.encrypt_server(bob.kx_pk, msg, aad) + aclear, clear_aad = bob.decrypt_client(alice.kx_pk, alice_ctxt, len(aad)) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/public.rst new/libnacl-2.1.0/doc/topics/public.rst --- old/libnacl-1.7.2/doc/topics/public.rst 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/public.rst 2023-08-06 23:22:51.000000000 +0200 @@ -84,7 +84,9 @@ import libnacl.public - tom = libnacl.public.PublicKey(tom_public_key_hex) + tom_secret = libnacl.public.SecretKey() + + tom = libnacl.public.PublicKey(tom_secret.pk) raw_pk = tom.pk hex_pk = tom.hex_pk() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/raw_public.rst new/libnacl-2.1.0/doc/topics/raw_public.rst --- old/libnacl-1.7.2/doc/topics/raw_public.rst 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/raw_public.rst 2023-08-06 23:22:51.000000000 +0200 @@ -20,8 +20,8 @@ import libnacl - alice_pk, alice_sk = libnacl.crypto_keypair() - bob_pk, bob_sk = libnacl.crypto_keypair() + alice_pk, alice_sk = libnacl.crypto_box_keypair() + bob_pk, bob_sk = libnacl.crypto_box_keypair() Once the keys have been generated a cryptographic box needs to be created. The cryptographic box takes the party's secret key and the receiving party's public @@ -63,8 +63,8 @@ import libnacl import libnacl.utils - alice_pk, alice_sk = libnacl.crypto_keypair() - bob_pk, bob_sk = libnacl.crypto_keypair() + alice_pk, alice_sk = libnacl.crypto_box_keypair() + bob_pk, bob_sk = libnacl.crypto_box_keypair() nonce = libnacl.utils.rand_nonce() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/raw_sealed.rst new/libnacl-2.1.0/doc/topics/raw_sealed.rst --- old/libnacl-1.7.2/doc/topics/raw_sealed.rst 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/raw_sealed.rst 2023-08-06 23:22:51.000000000 +0200 @@ -2,7 +2,7 @@ Raw Sealed Box Encryption ========================= -Sealed box is a variant of :doc:`public key encryption scheme </raw_public.rst>` +Sealed box is a variant of :doc:`public key encryption scheme </topics/raw_public>` where the sender is not authenticated. This is done by generating an ephemeral key pair, which the public key is prefixed to the cipher text. @@ -12,7 +12,7 @@ import libnacl - pk, sk = libnacl.crypto_keypair() + pk, sk = libnacl.crypto_box_keypair() Then a sealed box is created by the sender, using the receiver's public key @@ -33,7 +33,7 @@ import libnacl - pk, sk = libnacl.crypto_keypair() + pk, sk = libnacl.crypto_box_keypair() msg = 'Quiet, quiet. Quiet! There are ways of telling whether she is a witch.' box = libnacl.crypto_box_seal(msg, pk) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/raw_sign.rst new/libnacl-2.1.0/doc/topics/raw_sign.rst --- old/libnacl-1.7.2/doc/topics/raw_sign.rst 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/raw_sign.rst 2023-08-06 23:22:51.000000000 +0200 @@ -37,7 +37,7 @@ The signed message is really just the plain text of the message prepended with the signature. The crypto_sign_open function will read the signed message -and return me original message without the signature: +and return the original message without the signature: .. code-block:: python diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/releases/1.9.0.rst new/libnacl-2.1.0/doc/topics/releases/1.9.0.rst --- old/libnacl-1.7.2/doc/topics/releases/1.9.0.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/releases/1.9.0.rst 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,7 @@ +=========================== +libnacl 1.9.0 Release Notes +=========================== + +This release is a little overdue, it fixes a number of documentation issues +and adds a few convenience features. It also migrates the build system to poetry +and fixes the documentation build on readthedocs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/releases/2.0.0.rst new/libnacl-2.1.0/doc/topics/releases/2.0.0.rst --- old/libnacl-1.7.2/doc/topics/releases/2.0.0.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/releases/2.0.0.rst 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,9 @@ +=========================== +libnacl 2.0.0 Release Notes +=========================== + +Add Support for AEAD and AEAD Classes +===================================== + +Added classes to the libnacl.aead module allowing for the use of +XChaCha20-Poly1305-IETF, ChaCha20-Poly1305-IETF, and AES256-GCM. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/releases/2.1.0.rst new/libnacl-2.1.0/doc/topics/releases/2.1.0.rst --- old/libnacl-1.7.2/doc/topics/releases/2.1.0.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/releases/2.1.0.rst 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,21 @@ +=========================== +libnacl 2.1.0 Release Notes +=========================== + +Add Support for the Key Exchange System +======================================= + +Added the libnacl.kx module. This module contains the ExchangeKey class. + +The ExchangeKey class makes it easy to use AEAD encryption with an +exchange key setup. The class works much like a sealed box but allows +for the creation of the exchange keys. + +This makes it very easy to set up a system using AEAD and exchange keys. + +Fix issues with pyproject.toml +============================== + +The 2.0.0 release introduced the use of poetry into libnacl, unfortunately I +made a mistake in the pyproject.toml file. Thanks for @mgorny for catching the +issue and getting a PR in. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/doc/topics/secret.rst new/libnacl-2.1.0/doc/topics/secret.rst --- old/libnacl-1.7.2/doc/topics/secret.rst 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/doc/topics/secret.rst 2023-08-06 23:22:51.000000000 +0200 @@ -6,19 +6,21 @@ and decryption of messages. One of the classic examples from history of secret key, or symmetric, encryption is the Enigma machine. -The SecretBox class in libnacl.secret makes this type of encryption very easy +The SecretBoxEasy class in libnacl.secret_easy makes this type of encryption very easy to execute: .. code-block:: python + import libnacl.secret_easy + msg = b'But then of course African swallows are not migratory.' # Create a SecretBox object, if not passed in the secret key is # Generated purely from random data - box = libnacl.secret.SecretBox() + box = libnacl.secret_easy.SecretBoxEasy() # Messages can now be safely encrypted ctxt = box.encrypt(msg) # An additional box can be created from the original box secret key - box2 = libnacl.secret.SecretBox(box.sk) + box2 = libnacl.secret_easy.SecretBoxEasy(box.sk) # Messages can now be easily encrypted and decrypted clear1 = box.decrypt(ctxt) clear2 = box2.decrypt(ctxt) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/__init__.py new/libnacl-2.1.0/libnacl/__init__.py --- old/libnacl-1.7.2/libnacl/__init__.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/__init__.py 2023-08-06 23:22:51.000000000 +0200 @@ -4,7 +4,7 @@ ''' # pylint: disable=C0103 # Import python libs -import ctypes +import ctypes, ctypes.util import sys import os @@ -16,6 +16,10 @@ Locate the nacl c libs to use ''' # Import libsodium + l_path = ctypes.util.find_library('sodium') + if l_path is not None: + return ctypes.cdll.LoadLibrary(l_path) + if sys.platform.startswith('win'): try: return ctypes.cdll.LoadLibrary('libsodium') @@ -113,11 +117,16 @@ crypto_aead_chacha20poly1305_ietf_KEYBYTES = nacl.crypto_aead_chacha20poly1305_ietf_keybytes() crypto_aead_chacha20poly1305_ietf_NPUBBYTES = nacl.crypto_aead_chacha20poly1305_ietf_npubbytes() crypto_aead_chacha20poly1305_ietf_ABYTES = nacl.crypto_aead_chacha20poly1305_ietf_abytes() + crypto_aead_xchacha20poly1305_ietf_KEYBYTES = nacl.crypto_aead_xchacha20poly1305_ietf_keybytes() + crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = nacl.crypto_aead_xchacha20poly1305_ietf_npubbytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES = nacl.crypto_aead_xchacha20poly1305_ietf_abytes() HAS_AEAD_CHACHA20POLY1305_IETF = True + HAS_AEAD_XCHACHA20POLY1305_IETF = True HAS_AEAD = True except AttributeError: HAS_AEAD_AES256GCM = False HAS_AEAD_CHACHA20POLY1305_IETF = False + HAS_AEAD_XCHACHA20POLY1305_IETF = False HAS_AEAD = False crypto_box_SECRETKEYBYTES = nacl.crypto_box_secretkeybytes() @@ -770,6 +779,46 @@ return c.raw +def crypto_aead_xchacha20poly1305_ietf_encrypt(message, aad, nonce, key): + """Encrypts and authenticates a message with public additional data using the given secret key, and nonce + + Args: + message (bytes): a message to encrypt + aad (bytes): additional public data to authenticate + nonce (bytes): nonce, does not have to be confidential must be + `crypto_aead_xchacha20poly1305_ietf_NPUBBYTES` in length + key (bytes): secret key, must be `crypto_aead_chacha20poly1305_ietf_KEYBYTES` in + length + + Returns: + bytes: the ciphertext + + Raises: + ValueError: if arguments' length is wrong or the operation has failed. + """ + if not HAS_AEAD_XCHACHA20POLY1305_IETF: + raise ValueError('Underlying Sodium library does not support IETF variant of ChaCha20Poly1305 AEAD') + + if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: + raise ValueError('Invalid key') + + if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: + raise ValueError('Invalid nonce') + + length = len(message) + crypto_aead_xchacha20poly1305_ietf_ABYTES + clen = ctypes.c_ulonglong() + c = ctypes.create_string_buffer(length) + ret = nacl.crypto_aead_xchacha20poly1305_ietf_encrypt( + c, ctypes.pointer(clen), + message, ctypes.c_ulonglong(len(message)), + aad, ctypes.c_ulonglong(len(aad)), + None, + nonce, key) + if ret: + raise ValueError('Failed to encrypt message') + return c.raw + + def crypto_aead_aes256gcm_decrypt(ctxt, aad, nonce, key): """ Decrypts a ciphertext ctxt given the key, nonce, and aad. If the aad @@ -828,6 +877,34 @@ return m.raw +def crypto_aead_xchacha20poly1305_ietf_decrypt(ctxt, aad, nonce, key): + """ + Decrypts a ciphertext ctxt given the key, nonce, and aad. If the aad + or ciphertext were altered then the decryption will fail. + """ + if not HAS_AEAD_CHACHA20POLY1305_IETF: + raise ValueError('Underlying Sodium library does not support IETF variant of ChaCha20Poly1305 AEAD') + + if len(key) != crypto_aead_xchacha20poly1305_ietf_KEYBYTES: + raise ValueError('Invalid key') + + if len(nonce) != crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: + raise ValueError('Invalid nonce') + + length = len(ctxt)-crypto_aead_xchacha20poly1305_ietf_ABYTES + mlen = ctypes.c_ulonglong() + m = ctypes.create_string_buffer(length) + + ret = nacl.crypto_aead_xchacha20poly1305_ietf_decrypt( + m, ctypes.byref(mlen), + None, + ctxt, ctypes.c_ulonglong(len(ctxt)), + aad, ctypes.c_ulonglong(len(aad)), + nonce, key) + if ret: + raise ValueError('Failed to decrypt message') + return m.raw + # Symmetric Encryption @@ -1180,7 +1257,7 @@ ''' size = int(subkey_size) buf = ctypes.create_string_buffer(size) - nacl.crypto_kdf_derive_from_key(buf, subkey_size, subkey_id, context, master_key) + nacl.crypto_kdf_derive_from_key(buf, subkey_size, ctypes.c_ulonglong(subkey_id), context, master_key) return buf.raw # Key Exchange API diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/aead.py new/libnacl-2.1.0/libnacl/aead.py --- old/libnacl-1.7.2/libnacl/aead.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/aead.py 2023-08-06 23:22:51.000000000 +0200 @@ -20,21 +20,36 @@ raise ValueError('Invalid key') self.sk = key self.usingAES = False + self.usingXCHACHA = False + super().__init__() def useAESGCM(self): self.usingAES = True return self + def useXCHACHA(self): + self.usingXCHACHA = True + return self + def encrypt(self, msg, aad, nonce=None, pack_nonce_aad=True): ''' Encrypt the given message. If a nonce is not given it will be generated via the rand_nonce function ''' if nonce is None: - nonce = libnacl.utils.rand_aead_nonce() - if len(nonce) != libnacl.crypto_aead_aes256gcm_NPUBBYTES: - raise ValueError('Invalid nonce') - if self.usingAES: + if self.usingXCHACHA: + nonce = libnacl.utils.rand_aead_xchacha_nonce() + else: + nonce = libnacl.utils.rand_aead_nonce() + if self.usingXCHACHA: + if len(nonce) != libnacl.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: + raise ValueError('Invalid nonce') + else: + if len(nonce) != libnacl.crypto_aead_aes256gcm_NPUBBYTES: + raise ValueError('Invalid nonce') + if self.usingXCHACHA: + ctxt = libnacl.crypto_aead_xchacha20poly1305_ietf_encrypt(msg, aad, nonce, self.sk) + elif self.usingAES: ctxt = libnacl.crypto_aead_aes256gcm_encrypt(msg, aad, nonce, self.sk) else: ctxt = libnacl.crypto_aead_chacha20poly1305_ietf_encrypt(msg, aad, nonce, self.sk) @@ -50,10 +65,18 @@ extracted from the message ''' aad = ctxt[:aadLen] - nonce = ctxt[aadLen:aadLen+libnacl.crypto_aead_aes256gcm_NPUBBYTES] - ctxt = ctxt[aadLen+libnacl.crypto_aead_aes256gcm_NPUBBYTES:] - if len(nonce) != libnacl.crypto_aead_aes256gcm_NPUBBYTES: - raise ValueError('Invalid nonce') + if self.usingXCHACHA: + nonce = ctxt[aadLen:aadLen+libnacl.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES] + ctxt = ctxt[aadLen+libnacl.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES:] + if len(nonce) != libnacl.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: + raise ValueError('Invalid nonce') + else: + nonce = ctxt[aadLen:aadLen+libnacl.crypto_aead_aes256gcm_NPUBBYTES] + ctxt = ctxt[aadLen+libnacl.crypto_aead_aes256gcm_NPUBBYTES:] + if len(nonce) != libnacl.crypto_aead_aes256gcm_NPUBBYTES: + raise ValueError('Invalid nonce') + if self.usingXCHACHA: + return libnacl.crypto_aead_xchacha20poly1305_ietf_decrypt(ctxt, aad, nonce, self.sk) if self.usingAES: return libnacl.crypto_aead_aes256gcm_decrypt(ctxt, aad, nonce, self.sk) return libnacl.crypto_aead_chacha20poly1305_ietf_decrypt(ctxt, aad, nonce, self.sk) @@ -68,3 +91,20 @@ if self.usingAES: return libnacl.crypto_aead_aes256gcm_decrypt(ctxt, aad, nonce, self.sk) return libnacl.crypto_aead_chacha20poly1305_ietf_decrypt(ctxt, aad, nonce, self.sk) + + +class AEAD_AESGCM(AEAD): + def __init__(self, key=None): + super().__init__(key) + self.useAESGCM() + + +class AEAD_XCHACHA(AEAD): + def __init__(self, key=None): + super().__init__(key) + self.useXCHACHA() + + +class AEAD_CHACHA(AEAD): + def __init__(self, key=None): + super().__init__(key) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/base.py new/libnacl-2.1.0/libnacl/base.py --- old/libnacl-1.7.2/libnacl/base.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/base.py 2023-08-06 23:22:51.000000000 +0200 @@ -13,16 +13,29 @@ ''' Include methods for key management convenience ''' + def __init__(self): + self.sk_hex = self.hex_sk() + self.pk_hex = self.hex_pk() + self.kx_sk_hex = self.hex_kx_sk() + self.kx_pk_hex = self.hex_kx_pk() + self.vk_hex = self.hex_vk() + def hex_sk(self): if hasattr(self, 'sk'): return libnacl.encode.hex_encode(self.sk) - else: - return '' def hex_pk(self): if hasattr(self, 'pk'): return libnacl.encode.hex_encode(self.pk) + def hex_kx_pk(self): + if hasattr(self, 'kx_pk'): + return libnacl.encode.hex_encode(self.kx_pk) + + def hex_kx_sk(self): + if hasattr(self, 'kx_sk'): + return libnacl.encode.hex_encode(self.kx_sk) + def hex_vk(self): if hasattr(self, 'vk'): return libnacl.encode.hex_encode(self.vk) @@ -38,12 +51,18 @@ pre = {} sk = self.hex_sk() pk = self.hex_pk() + kx_sk = self.hex_kx_sk() + kx_pk = self.hex_kx_pk() vk = self.hex_vk() seed = self.hex_seed() if sk: pre['priv'] = sk.decode('utf-8') if pk: pre['pub'] = pk.decode('utf-8') + if kx_sk: + pre['kx_priv'] = kx_sk.decode('utf-8') + if kx_pk: + pre['kx_pub'] = kx_pk.decode('utf-8') if vk: pre['verify'] = vk.decode('utf-8') if seed: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/dual.py new/libnacl-2.1.0/libnacl/dual.py --- old/libnacl-1.7.2/libnacl/dual.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/dual.py 2023-08-06 23:22:51.000000000 +0200 @@ -20,6 +20,7 @@ self.seed = self.signer.seed self.pk = self.crypt.pk self.vk = self.signer.vk + super().__init__() def sign(self, msg): ''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/kx.py new/libnacl-2.1.0/libnacl/kx.py --- old/libnacl-1.7.2/libnacl/kx.py 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/kx.py 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,83 @@ +""" +Implementation of the X25519 Key Exchange function. These classes make executing a key +exchange simple. +""" +import libnacl +import libnacl.base +import libnacl.utils + + +class ExchangeKey(libnacl.base.BaseKey): + """ + The class used to manage key exchange keys + """ + def __init__(self, kx_sk=None, enc=None): + if kx_sk is None: + self.kx_pk, self.kx_sk = libnacl.crypto_kx_keypair() + elif len(kx_sk) == libnacl.libnacl.crypto_kx_SECRETKEYBYTES: + self.kx_sk = kx_sk + self.kx_pk = libnacl.crypto_scalarmult_base(kx_sk) + if enc is None: + self.enc = "xchacha" + elif enc in ("xchacha", "aesgcm", "chacha"): + self.enc = enc + else: + raise ValueError(f"Invalid encryption type passed: {enc}") + + def get_crypt(self, key): + return getattr(self, f"get_{self.enc}")(key) + + def get_xchacha(self, key): + return libnacl.aead.AEAD_XCHACHA(key) + + def get_chacha(self, key): + return libnacl.aead.AEAD_CHACHA(key) + + def get_aesgcm(self, key): + return libnacl.aead.AEAD_AESGCM(key) + + def client_session_keys(self, remote_pk): + """ + Takes a remote public key and derives the rx and tx session keys + """ + return libnacl.crypto_kx_client_session_keys(self.kx_pk, self.kx_sk, remote_pk) + + def server_session_keys(self, remote_pk): + """ + Takes a remote public key and derives the rx and tx session keys + """ + return libnacl.crypto_kx_server_session_keys(self.kx_pk, self.kx_sk, remote_pk) + + def encrypt_client(self, remote_pk, msg, ad): + """ + Encrypt the given message using the remote_sk + """ + rx, tx, status = self.client_session_keys(remote_pk) + + crypter = self.get_crypt(tx) + return crypter.encrypt(msg, ad) + + def encrypt_server(self, remote_pk, msg, ad): + """ + Encrypt the given message using the remote_sk + """ + rx, tx, status = self.server_session_keys(remote_pk) + + crypter = self.get_crypt(tx) + return crypter.encrypt(msg, ad) + + def decrypt_client(self, remote_pk, ctxt, len_ad): + rx, tx, status = self.client_session_keys(remote_pk) + + crypter = self.get_crypt(rx) + clear = crypter.decrypt(ctxt, len_ad) + #ad = ctxt[:len_ad] + return clear + + def decrypt_server(self, remote_pk, ctxt, len_ad): + rx, tx, status = self.server_session_keys(remote_pk) + + crypter = self.get_crypt(rx) + clear = crypter.decrypt(ctxt, len_ad) + #ad = ctxt[:len_ad] + return clear diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/public.py new/libnacl-2.1.0/libnacl/public.py --- old/libnacl-1.7.2/libnacl/public.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/public.py 2023-08-06 23:22:51.000000000 +0200 @@ -19,6 +19,7 @@ self.pk = pk else: raise ValueError('Passed in invalid public key') + super().__init__() def __eq__(self, other): if isinstance(other, self.__class__): @@ -48,6 +49,7 @@ self.pk = libnacl.crypto_scalarmult_base(sk) else: raise ValueError('Passed in invalid secret key') + super().__init__() def __eq__(self, other): if isinstance(other, self.__class__): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/secret_easy.py new/libnacl-2.1.0/libnacl/secret_easy.py --- old/libnacl-1.7.2/libnacl/secret_easy.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/secret_easy.py 2023-08-06 23:22:51.000000000 +0200 @@ -18,6 +18,7 @@ if len(key) != libnacl.crypto_secretbox_KEYBYTES: raise ValueError('Invalid key') self.sk = key + super().__init__() def encrypt(self, msg, nonce=None, pack_nonce=True): ''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/sign.py new/libnacl-2.1.0/libnacl/sign.py --- old/libnacl-1.7.2/libnacl/sign.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/sign.py 2023-08-06 23:22:51.000000000 +0200 @@ -24,6 +24,7 @@ seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) self.vk, self.sk = libnacl.crypto_sign_seed_keypair(seed) self.seed = seed + super().__init__() def sign(self, msg): ''' @@ -47,6 +48,7 @@ Create a verification key from a hex encoded vkey ''' self.vk = libnacl.encode.hex_decode(vk_hex) + super().__init__() def verify(self, msg): ''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/utils.py new/libnacl-2.1.0/libnacl/utils.py --- old/libnacl-1.7.2/libnacl/utils.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/utils.py 2023-08-06 23:22:51.000000000 +0200 @@ -47,6 +47,9 @@ elif 'priv' in key_data and 'pub' in key_data: return libnacl.public.SecretKey( libnacl.encode.hex_decode(key_data['priv'])) + elif 'kx_priv' in key_data and 'kx_pub' in key_data: + return libnacl.kx.ExchangeKey( + libnacl.encode.hex_decode(key_data['kx_priv'])) elif 'sign' in key_data: return libnacl.sign.Signer( libnacl.encode.hex_decode(key_data['sign'])) @@ -83,6 +86,14 @@ return libnacl.randombytes(libnacl.crypto_aead_aes256gcm_NPUBBYTES) +def rand_aead_xchacha_nonce(): + ''' + Generates and returns a random bytestring of the size defined in libsodium + as crypto_aead_aes256gcm_NPUBBYTES and crypto_aead_chacha20poly1305_ietf_NPUBBYTES + ''' + return libnacl.randombytes(libnacl.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES) + + def rand_nonce(): ''' Generates and returns a random bytestring of the size defined in libsodium diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/libnacl/version.py new/libnacl-2.1.0/libnacl/version.py --- old/libnacl-1.7.2/libnacl/version.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/libnacl/version.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -version = "1.7.2" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/pyproject.toml new/libnacl-2.1.0/pyproject.toml --- old/libnacl-1.7.2/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/pyproject.toml 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,40 @@ +[tool.poetry] +name = "libnacl" +version = "2.1.0" +description = "Python bindings for libsodium based on ctypes" +authors = ["Thomas S Hatch <thatc...@gmail.com>"] +license = "Apache-2.0" +homepage="https://libnacl.readthedocs.org" +repository="https://github.com/saltstack/libnacl" +documentation="https://libnacl.readthedocs.org" +readme = "README.rst" +classifiers = [ + "Operating System :: OS Independent", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Security :: Cryptography", + ] +include = [ + { path = "doc", format = "sdist" }, + { path = "tests", format = "sdist" }, +] + +[tool.poetry.dependencies] +python = "^3.4" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/setup.cfg new/libnacl-2.1.0/setup.cfg --- old/libnacl-1.7.2/setup.cfg 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100 @@ -1,2 +0,0 @@ -[bdist_wheel] -universal = 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/setup.py new/libnacl-2.1.0/setup.py --- old/libnacl-1.7.2/setup.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/setup.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from setuptools import setup - -NAME = "libnacl" -DESC = "Python bindings for libsodium based on ctypes" - -# Version info -- read without importing -_locals = {} -with open("libnacl/version.py") as fp: - exec(fp.read(), None, _locals) -VERSION = _locals["version"] - -setup( - name=NAME, - version=VERSION, - description=DESC, - author="Thomas S Hatch", - author_email="tha...@saltstack.com", - url="https://libnacl.readthedocs.org/", - classifiers=[ - "Operating System :: OS Independent", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 2.6", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "Topic :: Security :: Cryptography", - ], - packages=["libnacl"], -) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/tests/unit/test_aead.py new/libnacl-2.1.0/tests/unit/test_aead.py --- old/libnacl-1.7.2/tests/unit/test_aead.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/tests/unit/test_aead.py 2023-08-06 23:22:51.000000000 +0200 @@ -23,6 +23,23 @@ clear3 = box.decrypt(ctxt2, len(aad)) self.assertEqual(clear3, msg) + @unittest.skipUnless(libnacl.HAS_AEAD_AES256GCM, 'AES256-GCM AEAD not available') + def test_gcm_aead_class(self): + msg = b"You've got two empty halves of coconuts and your bangin' 'em together." + aad = b'\x00\x11\x22\x33' + box = libnacl.aead.AEAD_AESGCM() + ctxt = box.encrypt(msg, aad) + self.assertNotEqual(msg, ctxt) + + box2 = libnacl.aead.AEAD_AESGCM(box.sk) + clear1 = box.decrypt(ctxt, len(aad)) + self.assertEqual(msg, clear1) + clear2 = box2.decrypt(ctxt, len(aad)) + self.assertEqual(clear1, clear2) + ctxt2 = box2.encrypt(msg, aad) + clear3 = box.decrypt(ctxt2, len(aad)) + self.assertEqual(clear3, msg) + @unittest.skipUnless(libnacl.HAS_AEAD_CHACHA20POLY1305_IETF, 'IETF variant of ChaCha20Poly1305 AEAD not available') def test_ietf_aead(self): msg = b"Our King? Well i didn't vote for you!!" @@ -38,4 +55,57 @@ self.assertEqual(clear1, clear2) ctxt2 = box2.encrypt(msg, aad) clear3 = box.decrypt(ctxt2, len(aad)) + + @unittest.skipUnless(libnacl.HAS_AEAD_CHACHA20POLY1305_IETF, 'IETF variant of ChaCha20Poly1305 AEAD not available') + def test_ietf_aead_class(self): + msg = b"Our King? Well i didn't vote for you!!" + aad = b'\x00\x11\x22\x33' + box = libnacl.aead.AEAD_CHACHA() + ctxt = box.encrypt(msg, aad) + self.assertNotEqual(msg, ctxt) + + box2 = libnacl.aead.AEAD_CHACHA(box.sk) + clear1 = box.decrypt(ctxt, len(aad)) + self.assertEqual(msg, clear1) + clear2 = box2.decrypt(ctxt, len(aad)) + self.assertEqual(clear1, clear2) + ctxt2 = box2.encrypt(msg, aad) + clear3 = box.decrypt(ctxt2, len(aad)) + + @unittest.skipUnless(libnacl.HAS_AEAD_XCHACHA20POLY1305_IETF, 'IETF variant of xChaCha20Poly1305 AEAD not available') + def test_ietf_aead_xchacha(self): + msg = b"Our King? Well i didn't vote for you!!" + aad = b'\x00\x11\x22\x33' + box = libnacl.aead.AEAD().useXCHACHA() + ctxt = box.encrypt(msg, aad) + self.assertNotEqual(msg, ctxt) + + box2 = libnacl.aead.AEAD(box.sk).useXCHACHA() + clear1 = box.decrypt(ctxt, len(aad)) + self.assertEqual(msg, clear1) + clear2 = box2.decrypt(ctxt, len(aad)) + self.assertEqual(clear1, clear2) + ctxt2 = box2.encrypt(msg, aad) + clear3 = box.decrypt(ctxt2, len(aad)) + self.assertEqual(clear3, msg) self.assertEqual(clear3, msg) + + + @unittest.skipUnless(libnacl.HAS_AEAD_XCHACHA20POLY1305_IETF, 'IETF variant of xChaCha20Poly1305 AEAD not available') + def test_ietf_aead_xchacha_class(self): + msg = b"Our King? Well i didn't vote for you!!" + aad = b'\x00\x11\x22\x33' + box = libnacl.aead.AEAD_XCHACHA() + ctxt = box.encrypt(msg, aad) + self.assertNotEqual(msg, ctxt) + + box2 = libnacl.aead.AEAD_XCHACHA(box.sk) + clear1 = box.decrypt(ctxt, len(aad)) + self.assertEqual(msg, clear1) + clear2 = box2.decrypt(ctxt, len(aad)) + self.assertEqual(clear1, clear2) + ctxt2 = box2.encrypt(msg, aad) + clear3 = box.decrypt(ctxt2, len(aad)) + self.assertEqual(clear3, msg) + self.assertEqual(clear3, msg) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/tests/unit/test_dual.py new/libnacl-2.1.0/tests/unit/test_dual.py --- old/libnacl-1.7.2/tests/unit/test_dual.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/tests/unit/test_dual.py 2023-08-06 23:22:51.000000000 +0200 @@ -25,6 +25,9 @@ aclear = alice_box.decrypt(alice_ctxt) self.assertEqual(msg, aclear) self.assertNotEqual(bob_ctxt, alice_ctxt) + self.assertEqual(bob.pk_hex, bob.hex_pk()) + self.assertEqual(bob.sk_hex, bob.hex_sk()) + self.assertEqual(bob.vk_hex, bob.hex_vk()) def test_publickey(self): ''' @@ -39,6 +42,9 @@ self.assertNotEqual(msg, bob_ctxt) bclear = alice_box.decrypt(bob_ctxt) self.assertEqual(msg, bclear) + self.assertEqual(bob.pk_hex, bob.hex_pk()) + self.assertEqual(bob.sk_hex, bob.hex_sk()) + self.assertEqual(bob.vk_hex, bob.hex_vk()) def test_sign(self): msg = (b'Well, that\'s no ordinary rabbit. That\'s the most foul, ' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/tests/unit/test_kx.py new/libnacl-2.1.0/tests/unit/test_kx.py --- old/libnacl-1.7.2/tests/unit/test_kx.py 1970-01-01 01:00:00.000000000 +0100 +++ new/libnacl-2.1.0/tests/unit/test_kx.py 2023-08-06 23:22:51.000000000 +0200 @@ -0,0 +1,35 @@ +# Import libnacl libs +import libnacl.kx + +# Import python libs +import unittest + +class TestKX(unittest.TestCase): + ''' + ''' + def test_exchange_key(self): + ''' + ''' + msg = b'You\'ve got two empty halves of coconut and you\'re bangin\' \'em together.' + ad = b'A Duck!' + # Make Bob and Alice Exchange Keys + bob = libnacl.kx.ExchangeKey() + alice = libnacl.kx.ExchangeKey() + # Encrypt with bob as clientm alic as server + bob_ctxt = bob.encrypt_client(alice.kx_pk, msg, ad) + self.assertNotEqual(msg, bob_ctxt) + bclear = alice.decrypt_server(bob.kx_pk, bob_ctxt, len(ad)) + self.assertEqual(ad, bob_ctxt[:len(ad)]) + self.assertEqual(msg, bclear) + alice_ctxt = alice.encrypt_server(bob.kx_pk, msg, ad) + aclear = bob.decrypt_client(alice.kx_pk, alice_ctxt, len(ad)) + self.assertEqual(ad, alice_ctxt[:len(ad)]) + self.assertEqual(msg, aclear) + self.assertNotEqual(msg, alice_ctxt) + # Encrypt with Alice as client bob as server + alice_ctxt = alice.encrypt_client(bob.kx_pk, msg, ad) + self.assertNotEqual(msg, alice_ctxt) + bclear = bob.decrypt_server(alice.kx_pk, alice_ctxt, len(ad)) + self.assertEqual(ad, alice_ctxt[:len(ad)]) + self.assertEqual(msg, bclear) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnacl-1.7.2/tests/unit/test_public.py new/libnacl-2.1.0/tests/unit/test_public.py --- old/libnacl-1.7.2/tests/unit/test_public.py 2020-11-03 22:34:59.000000000 +0100 +++ new/libnacl-2.1.0/tests/unit/test_public.py 2023-08-06 23:22:51.000000000 +0200 @@ -24,6 +24,8 @@ aclear = alice_box.decrypt(alice_ctxt) self.assertEqual(msg, aclear) self.assertNotEqual(bob_ctxt, alice_ctxt) + self.assertEqual(bob.pk_hex, bob.hex_pk()) + self.assertEqual(bob.sk_hex, bob.hex_sk()) def test_publickey(self): ''' @@ -38,4 +40,5 @@ self.assertNotEqual(msg, bob_ctxt) bclear = alice_box.decrypt(bob_ctxt) self.assertEqual(msg, bclear) + self.assertEqual(bob.sk_hex, bob.hex_sk())