summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2023-08-08 16:13:00 +0100
committerColin Watson <cjwatson@debian.org>2023-08-08 16:13:00 +0100
commit2287f5d72438282d26312d4ecb20c50230475a8e (patch)
tree609e7232f4f6c60e0b79637763a474afbc2a1be3
parent1cfc83800c8b82e6919291bb4f4bde580ea89821 (diff)
New upstream version 2.1.0
-rw-r--r--AUTHORS3
-rw-r--r--LICENSE2
-rw-r--r--MANIFEST.in6
-rw-r--r--PKG-INFO93
-rw-r--r--doc/conf.py9
-rw-r--r--doc/index.rst1
-rw-r--r--doc/topics/aead.rst33
-rw-r--r--doc/topics/kx.rst38
-rw-r--r--doc/topics/public.rst4
-rw-r--r--doc/topics/raw_sealed.rst2
-rw-r--r--doc/topics/releases/1.9.0.rst7
-rw-r--r--doc/topics/releases/2.0.0.rst9
-rw-r--r--doc/topics/releases/2.1.0.rst21
-rw-r--r--doc/topics/secret.rst8
-rw-r--r--libnacl.egg-info/PKG-INFO25
-rw-r--r--libnacl.egg-info/SOURCES.txt87
-rw-r--r--libnacl.egg-info/dependency_links.txt1
-rw-r--r--libnacl.egg-info/top_level.txt1
-rw-r--r--libnacl/__init__.py79
-rw-r--r--libnacl/aead.py56
-rw-r--r--libnacl/base.py23
-rw-r--r--libnacl/dual.py1
-rw-r--r--libnacl/kx.py83
-rw-r--r--libnacl/public.py2
-rw-r--r--libnacl/secret_easy.py1
-rw-r--r--libnacl/sign.py2
-rw-r--r--libnacl/utils.py11
-rw-r--r--libnacl/version.py2
-rw-r--r--pkg/rpm/python-libnacl.spec153
-rw-r--r--pkg/suse/python-libnacl.changes15
-rw-r--r--pkg/suse/python-libnacl.spec59
-rw-r--r--pyproject.toml40
-rw-r--r--setup.cfg7
-rw-r--r--setup.py36
-rw-r--r--tests/unit/test_aead.py70
-rw-r--r--tests/unit/test_dual.py6
-rw-r--r--tests/unit/test_kx.py35
-rw-r--r--tests/unit/test_public.py3
38 files changed, 604 insertions, 430 deletions
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index c43beb7..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,3 +0,0 @@
-Thomas S Hatch
-Sam Smith
-Pedro Algarvio
diff --git a/LICENSE b/LICENSE
index 8dd3877..d7c9058 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@ Apache License
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 --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index c5c3bf6..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,6 +0,0 @@
-include LICENSE
-include AUTHORS
-include README.rst
-recursive-include tests *.py
-recursive-include doc *
-recursive-include pkg *
diff --git a/PKG-INFO b/PKG-INFO
index 5b4fd06..dd219a1 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,25 +1,92 @@
Metadata-Version: 2.1
Name: libnacl
-Version: 1.8.0
+Version: 2.1.0
Summary: Python bindings for libsodium based on ctypes
-Home-page: https://libnacl.readthedocs.org/
+Home-page: https://libnacl.readthedocs.org
+License: Apache-2.0
Author: Thomas S Hatch
-Author-email: thatch@saltstack.com
-License: UNKNOWN
-Platform: UNKNOWN
-Classifier: Operating System :: OS Independent
+Author-email: thatch45@gmail.com
+Requires-Python: >=3.4,<4.0
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
Classifier: Topic :: Security :: Cryptography
-License-File: LICENSE
-License-File: AUTHORS
+Project-URL: Documentation, https://libnacl.readthedocs.org
+Project-URL: Repository, https://github.com/saltstack/libnacl
+Description-Content-Type: text/x-rst
+
+==============
+Python libnacl
+==============
+
+This library is used to gain direct access to the functions exposed by
+Daniel J. Bernstein's nacl library via libsodium. It has
+been constructed to maintain extensive documentation on how to use nacl
+as well as being completely portable. The file in libnacl/__init__.py
+can be pulled out and placed directly in any project to give a single file
+binding to all of nacl.
+
+Higher Level Classes
+====================
+
+The libnacl code also ships with many high level classes which make nacl
+cryptography easy and safe, for documentation please see:
+http://libnacl.readthedocs.org/
+
+Why libnacl
+===========
+
+There are a number of libraries out there binding to libsodium, so why make
+libnacl?
+
+1. libnacl does not have any non-python hard deps outside of libsodium
+2. libnacl does not need to be compiled
+3. libnacl is easy to package and very portable
+4. Inclusion of high level pythonic encryption classes
+5. Ability to have a single embeddable and transferable bindings file
+ that can be added directly to python applications without needing
+ to dep libnacl
+
+This makes libnacl very portable, very easy to use and easy to distribute.
+
+Install
+=======
+
+The libnacl code is easiy installed via a setup.py from the source or via pip.
+
+From Source:
+
+.. code-block:: bash
+
+ tar xvf libnacl-1.5.2.tar.gz
+ cd libnacl-1.5.2
+ python setup.py install
+
+Via Pip:
+
+.. code-block:: bash
+
+ pip install libnacl
+
+Remember that libnacl can be installed for python 2 and 3.
+
+Linux distributions
+-------------------
-UNKNOWN
+Libnacl is shiped with many linux distributions, check your distribution
+package manager for the package ``python-libnacl``, ``python2-libnacl``
+and/or ``python3-libnacl``.
diff --git a/doc/conf.py b/doc/conf.py
index 26dd69f..096bf5e 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -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 @@ master_doc = 'index'
# 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 @@ copyright = u'2020, Thomas S Hatch'
#
# 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 @@ texinfo_documents = [
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 --git a/doc/index.rst b/doc/index.rst
index 4638f71..8c146ed 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -11,6 +11,7 @@ Contents:
topics/secret
topics/sign
topics/dual
+ topics/aead
topics/utils
topics/raw_public
topics/raw_sealed
diff --git a/doc/topics/aead.rst b/doc/topics/aead.rst
new file mode 100644
index 0000000..9a5925e
--- /dev/null
+++ b/doc/topics/aead.rst
@@ -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 --git a/doc/topics/kx.rst b/doc/topics/kx.rst
new file mode 100644
index 0000000..0cec43e
--- /dev/null
+++ b/doc/topics/kx.rst
@@ -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 --git a/doc/topics/public.rst b/doc/topics/public.rst
index eb2f1bb..34f60be 100644
--- a/doc/topics/public.rst
+++ b/doc/topics/public.rst
@@ -84,7 +84,9 @@ To manage only the public key end, a public key object exists:
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 --git a/doc/topics/raw_sealed.rst b/doc/topics/raw_sealed.rst
index b2c890e..c1ce444 100644
--- a/doc/topics/raw_sealed.rst
+++ b/doc/topics/raw_sealed.rst
@@ -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.
diff --git a/doc/topics/releases/1.9.0.rst b/doc/topics/releases/1.9.0.rst
new file mode 100644
index 0000000..5a89077
--- /dev/null
+++ b/doc/topics/releases/1.9.0.rst
@@ -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 --git a/doc/topics/releases/2.0.0.rst b/doc/topics/releases/2.0.0.rst
new file mode 100644
index 0000000..2ab6d2d
--- /dev/null
+++ b/doc/topics/releases/2.0.0.rst
@@ -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 --git a/doc/topics/releases/2.1.0.rst b/doc/topics/releases/2.1.0.rst
new file mode 100644
index 0000000..ba22ebc
--- /dev/null
+++ b/doc/topics/releases/2.1.0.rst
@@ -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 --git a/doc/topics/secret.rst b/doc/topics/secret.rst
index 3690704..cffd224 100644
--- a/doc/topics/secret.rst
+++ b/doc/topics/secret.rst
@@ -6,19 +6,21 @@ Secret key encryption is the method of using a single key for both encryption
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 --git a/libnacl.egg-info/PKG-INFO b/libnacl.egg-info/PKG-INFO
deleted file mode 100644
index 5b4fd06..0000000
--- a/libnacl.egg-info/PKG-INFO
+++ /dev/null
@@ -1,25 +0,0 @@
-Metadata-Version: 2.1
-Name: libnacl
-Version: 1.8.0
-Summary: Python bindings for libsodium based on ctypes
-Home-page: https://libnacl.readthedocs.org/
-Author: Thomas S Hatch
-Author-email: thatch@saltstack.com
-License: UNKNOWN
-Platform: UNKNOWN
-Classifier: Operating System :: OS Independent
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Topic :: Security :: Cryptography
-License-File: LICENSE
-License-File: AUTHORS
-
-UNKNOWN
-
diff --git a/libnacl.egg-info/SOURCES.txt b/libnacl.egg-info/SOURCES.txt
deleted file mode 100644
index 2b20d14..0000000
--- a/libnacl.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-AUTHORS
-LICENSE
-MANIFEST.in
-README.rst
-setup.cfg
-setup.py
-doc/Makefile
-doc/conf.py
-doc/index.rst
-doc/topics/dual.rst
-doc/topics/public.rst
-doc/topics/raw_generichash.rst
-doc/topics/raw_hash.rst
-doc/topics/raw_public.rst
-doc/topics/raw_sealed.rst
-doc/topics/raw_secret.rst
-doc/topics/raw_sign.rst
-doc/topics/sealed.rst
-doc/topics/secret.rst
-doc/topics/sign.rst
-doc/topics/utils.rst
-doc/topics/releases/1.0.0.rst
-doc/topics/releases/1.1.0.rst
-doc/topics/releases/1.2.0.rst
-doc/topics/releases/1.3.0.rst
-doc/topics/releases/1.3.1.rst
-doc/topics/releases/1.3.2.rst
-doc/topics/releases/1.3.3.rst
-doc/topics/releases/1.3.4.rst
-doc/topics/releases/1.4.0.rst
-doc/topics/releases/1.4.1.rst
-doc/topics/releases/1.4.2.rst
-doc/topics/releases/1.4.3.rst
-doc/topics/releases/1.4.4.rst
-doc/topics/releases/1.4.5.rst
-doc/topics/releases/1.5.0.rst
-doc/topics/releases/1.5.1.rst
-doc/topics/releases/1.5.2.rst
-doc/topics/releases/1.6.0.rst
-doc/topics/releases/1.6.1.rst
-doc/topics/releases/1.7.1.rst
-doc/topics/releases/1.7.rst
-doc/topics/releases/index.rst
-libnacl/__init__.py
-libnacl/aead.py
-libnacl/base.py
-libnacl/blake.py
-libnacl/dual.py
-libnacl/encode.py
-libnacl/public.py
-libnacl/sealed.py
-libnacl/secret.py
-libnacl/secret_easy.py
-libnacl/sign.py
-libnacl/utils.py
-libnacl/version.py
-libnacl.egg-info/PKG-INFO
-libnacl.egg-info/SOURCES.txt
-libnacl.egg-info/dependency_links.txt
-libnacl.egg-info/top_level.txt
-pkg/rpm/python-libnacl.spec
-pkg/suse/python-libnacl.changes
-pkg/suse/python-libnacl.spec
-tests/runtests.py
-tests/unit/__init__.py
-tests/unit/test_aead.py
-tests/unit/test_auth_verify.py
-tests/unit/test_blake.py
-tests/unit/test_dual.py
-tests/unit/test_public.py
-tests/unit/test_raw_auth_sym.py
-tests/unit/test_raw_auth_sym_easy.py
-tests/unit/test_raw_generichash.py
-tests/unit/test_raw_hash.py
-tests/unit/test_raw_public.py
-tests/unit/test_raw_random.py
-tests/unit/test_raw_secret.py
-tests/unit/test_raw_secret_easy.py
-tests/unit/test_raw_sign.py
-tests/unit/test_save.py
-tests/unit/test_seal.py
-tests/unit/test_secret.py
-tests/unit/test_secret_easy.py
-tests/unit/test_sign.py
-tests/unit/test_stream.py
-tests/unit/test_verify.py
-tests/unit/test_version.py \ No newline at end of file
diff --git a/libnacl.egg-info/dependency_links.txt b/libnacl.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/libnacl.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libnacl.egg-info/top_level.txt b/libnacl.egg-info/top_level.txt
deleted file mode 100644
index d238ddf..0000000
--- a/libnacl.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-libnacl
diff --git a/libnacl/__init__.py b/libnacl/__init__.py
index 7649013..0f80f49 100644
--- a/libnacl/__init__.py
+++ b/libnacl/__init__.py
@@ -4,7 +4,7 @@ Wrap libsodium routines
'''
# pylint: disable=C0103
# Import python libs
-import ctypes
+import ctypes, ctypes.util
import sys
import os
@@ -16,6 +16,10 @@ def _get_nacl():
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 @@ if not DOC_RUN:
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 @@ def crypto_aead_chacha20poly1305_ietf_encrypt(message, aad, nonce, key):
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 @@ def crypto_aead_chacha20poly1305_ietf_decrypt(ctxt, aad, nonce, key):
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
diff --git a/libnacl/aead.py b/libnacl/aead.py
index db53b13..0a519b1 100644
--- a/libnacl/aead.py
+++ b/libnacl/aead.py
@@ -20,21 +20,36 @@ class AEAD(libnacl.base.BaseKey):
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 @@ class AEAD(libnacl.base.BaseKey):
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 @@ class AEAD(libnacl.base.BaseKey):
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 --git a/libnacl/base.py b/libnacl/base.py
index b115a47..66239a7 100644
--- a/libnacl/base.py
+++ b/libnacl/base.py
@@ -13,16 +13,29 @@ class BaseKey(object):
'''
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 @@ class BaseKey(object):
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 --git a/libnacl/dual.py b/libnacl/dual.py
index c48fb67..6203c19 100644
--- a/libnacl/dual.py
+++ b/libnacl/dual.py
@@ -20,6 +20,7 @@ class DualSecret(libnacl.base.BaseKey):
self.seed = self.signer.seed
self.pk = self.crypt.pk
self.vk = self.signer.vk
+ super().__init__()
def sign(self, msg):
'''
diff --git a/libnacl/kx.py b/libnacl/kx.py
new file mode 100644
index 0000000..4d995f6
--- /dev/null
+++ b/libnacl/kx.py
@@ -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 --git a/libnacl/public.py b/libnacl/public.py
index bac8609..0e6afa5 100644
--- a/libnacl/public.py
+++ b/libnacl/public.py
@@ -19,6 +19,7 @@ class PublicKey(libnacl.base.BaseKey):
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 @@ class SecretKey(libnacl.base.BaseKey):
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 --git a/libnacl/secret_easy.py b/libnacl/secret_easy.py
index 15dea1b..7ffad35 100644
--- a/libnacl/secret_easy.py
+++ b/libnacl/secret_easy.py
@@ -18,6 +18,7 @@ class SecretBoxEasy(libnacl.base.BaseKey):
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 --git a/libnacl/sign.py b/libnacl/sign.py
index 9dbd83f..03254cb 100644
--- a/libnacl/sign.py
+++ b/libnacl/sign.py
@@ -24,6 +24,7 @@ class Signer(libnacl.base.BaseKey):
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 @@ class Verifier(libnacl.base.BaseKey):
Create a verification key from a hex encoded vkey
'''
self.vk = libnacl.encode.hex_decode(vk_hex)
+ super().__init__()
def verify(self, msg):
'''
diff --git a/libnacl/utils.py b/libnacl/utils.py
index e06e078..bd22b91 100644
--- a/libnacl/utils.py
+++ b/libnacl/utils.py
@@ -47,6 +47,9 @@ def load_key(path_or_file, serial='json'):
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 @@ def rand_aead_nonce():
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 --git a/libnacl/version.py b/libnacl/version.py
deleted file mode 100644
index baca2f5..0000000
--- a/libnacl/version.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# -*- coding: utf-8 -*-
-version = "1.8.0"
diff --git a/pkg/rpm/python-libnacl.spec b/pkg/rpm/python-libnacl.spec
deleted file mode 100644
index 6b991c4..0000000
--- a/pkg/rpm/python-libnacl.spec
+++ /dev/null
@@ -1,153 +0,0 @@
-%if 0%{?fedora} > 12 || 0%{?rhel} > 6
-%global with_python3 1
-%endif
-
-%if 0%{?rhel} == 5
-%global pybasever 2.6
-%endif
-
-%{!?__python2: %global __python2 /usr/bin/python%{?pybasever}}
-%{!?python2_sitearch: %global python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
-%{!?python2_sitelib: %global python2_sitelib %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")}
-
-%global srcname libnacl
-
-Name: python-%{srcname}
-Version: 1.4.3
-Release: 1%{?dist}
-Summary: Python bindings for libsodium based on ctypes
-
-Group: Development/Libraries
-License: ASL 2.0
-URL: https://github.com/saltstack/libnacl
-Source0: https://pypi.python.org/packages/source/l/%{srcname}/%{srcname}-%{version}.tar.gz
-
-BuildRoot: %{_tmppath}/%{srcname}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildArch: noarch
-
-BuildRequires: libsodium
-Requires: libsodium >= 0.5.0
-
-%if ! (0%{?rhel} == 5)
-BuildRequires: python
-BuildRequires: python-devel
-BuildRequires: python-setuptools
-%endif
-
-%if 0%{?with_python3}
-BuildRequires: python3-devel
-BuildRequires: python3-setuptools
-%endif
-
-%description
-This library is used to gain direct access to the functions exposed by Daniel
-J. Bernstein's nacl library via libsodium. It has been constructed
-to maintain extensive documentation on how to use nacl as well as being
-completely portable. The file in libnacl/__init__.py can be pulled out and
-placed directly in any project to give a single file binding to all of nacl.
-
-This is the Python 2 build of the module.
-
-%if 0%{?with_python3}
-%package -n python3-%{srcname}
-Summary: Python bindings for libsodium based on ctypes
-Group: Development/Libraries
-Requires: libsodium
-
-%description -n python3-%{srcname}
-This library is used to gain direct access to the functions exposed by Daniel
-J. Bernstein's nacl library via libsodium. It has been constructed
-to maintain extensive documentation on how to use nacl as well as being
-completely portable. The file in libnacl/__init__.py can be pulled out and
-placed directly in any project to give a single file binding to all of nacl.
-
-This is the Python 3 build of the module.
-%endif
-
-%if 0%{?rhel} == 5
-%package -n python26-%{srcname}
-Summary: Python bindings for libsodium based on ctypes
-Group: Development/Libraries
-BuildRequires: python26
-BuildRequires: libsodium
-BuildRequires: python26-devel
-Requires: python26
-Requires: libsodium
-
-%description -n python26-%{srcname}
-This library is used to gain direct access to the functions exposed by Daniel
-J. Bernstein's nacl library via libsodium. It has been constructed
-to maintain extensive documentation on how to use nacl as well as being
-completely portable. The file in libnacl/__init__.py can be pulled out and
-placed directly in any project to give a single file binding to all of nacl.
-
-This is the Python 2 build of the module.
-%endif
-
-%prep
-%setup -q -n %{srcname}-%{version}
-
-%if 0%{?with_python3}
-rm -rf %{py3dir}
-cp -a . %{py3dir}
-%endif
-
-%build
-%{__python2} setup.py build
-
-%if 0%{?with_python3}
-pushd %{py3dir}
-%{__python3} setup.py build
-popd
-%endif
-
-%install
-rm -rf %{buildroot}
-%{__python2} setup.py install --skip-build --root %{buildroot}
-
-%if 0%{?with_python3}
-pushd %{py3dir}
-%{__python3} setup.py install --skip-build --root %{buildroot}
-popd
-%endif
-
-%clean
-rm -rf %{buildroot}
-
-%if 0%{?rhel} == 5
-%files -n python26-%{srcname}
-%defattr(-,root,root,-)
-%{python2_sitelib}/*
-%else
-%files
-%defattr(-,root,root,-)
-%{python2_sitelib}/*
-%endif
-
-%if 0%{?with_python3}
-%files -n python3-%{srcname}
-%defattr(-,root,root,-)
-%{python3_sitelib}/*
-%endif
-
-%changelog
-* Thu Sep 4 2014 Erik Johnson <erik@saltstack.com> - 1.3.5-1
-- Updated to 1.3.5
-
-* Fri Aug 22 2014 Erik Johnson <erik@saltstack.com> - 1.3.3-1
-- Updated to 1.3.3
-
-* Fri Aug 8 2014 Erik Johnson <erik@saltstack.com> - 1.3.2-1
-- Updated to 1.3.2
-
-* Fri Aug 8 2014 Erik Johnson <erik@saltstack.com> - 1.3.1-1
-- Updated to 1.3.1
-
-* Thu Aug 7 2014 Erik Johnson <erik@saltstack.com> - 1.3.0-1
-- Updated to 1.3.0
-
-* Fri Jun 20 2014 Erik Johnson <erik@saltstack.com> - 1.1.0-1
-- Updated to 1.1.0
-
-* Fri Jun 20 2014 Erik Johnson <erik@saltstack.com> - 1.0.0-1
-- Initial build
diff --git a/pkg/suse/python-libnacl.changes b/pkg/suse/python-libnacl.changes
deleted file mode 100644
index 4740656..0000000
--- a/pkg/suse/python-libnacl.changes
+++ /dev/null
@@ -1,15 +0,0 @@
--------------------------------------------------------------------
-Wed Jul 2 18:28:08 UTC 2014 - aboe76@gmail.com
-
-- Updated to 1.1.0
-
--------------------------------------------------------------------
-Fri Jun 20 15:10:52 UTC 2014 - aboe76@gmail.com
-
-- Simplified BuildRequirements to libsodium-devel
-
--------------------------------------------------------------------
-Mon Jun 9 10:53:12 UTC 2014 - aboe76@gmail.com
-
-- initial package
-
diff --git a/pkg/suse/python-libnacl.spec b/pkg/suse/python-libnacl.spec
deleted file mode 100644
index 2dc9810..0000000
--- a/pkg/suse/python-libnacl.spec
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# spec file for package python-libnacl
-#
-# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
-#
-# All modifications and additions to the file contributed by third parties
-# remain the property of their copyright owners, unless otherwise agreed
-# upon. The license for this file, and modifications and additions to the
-# file, is the same license as for the pristine package itself (unless the
-# license for the pristine package is not an Open Source License, in which
-# case the license is the MIT License). An "Open Source License" is a
-# license that conforms to the Open Source Definition (Version 1.9)
-# published by the Open Source Initiative.
-
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
-#
-
-Name: python-libnacl
-Version: 1.4.3
-Release: 0
-License: Apache-2.0
-Summary: Python bindings for libsodium based on ctypes
-Url: https://github.com/saltstack/libnacl
-Group: Development/Languages/Python
-Source0: https://pypi.python.org/packages/source/l/libnacl/libnacl-%{version}.tar.gz
-BuildRoot: %{_tmppath}/libnacl-%{version}-build
-
-BuildRequires: python-setuptools
-BuildRequires: python-devel
-BuildRequires: libsodium-devel
-BuildRequires: fdupes
-
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
-BuildArch: noarch
-%endif
-
-%description
-This library is used to gain direct access to the functions exposed by Daniel J. Bernstein's nacl library via libsodium.
-It has been constructed to maintain extensive documentation on how to use nacl as well as being completely portable. The file
-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}
-
-%build
-python setup.py build
-
-%install
-python setup.py install --prefix=%{_prefix} --root=%{buildroot} --optimize=1
-%fdupes %{buildroot}%{_prefix}
-
-%files
-%defattr(-,root,root)
-%{python_sitelib}/*
-
-%changelog \ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..514ddb0
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,40 @@
+[tool.poetry]
+name = "libnacl"
+version = "2.1.0"
+description = "Python bindings for libsodium based on ctypes"
+authors = ["Thomas S Hatch <thatch45@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 --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index adf5ed7..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-[bdist_wheel]
-universal = 1
-
-[egg_info]
-tag_build =
-tag_date = 0
-
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 79dda9c..0000000
--- a/setup.py
+++ /dev/null
@@ -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="thatch@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 --git a/tests/unit/test_aead.py b/tests/unit/test_aead.py
index b6dfa05..b404975 100644
--- a/tests/unit/test_aead.py
+++ b/tests/unit/test_aead.py
@@ -23,6 +23,23 @@ class TestAEAD(unittest.TestCase):
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 @@ class TestAEAD(unittest.TestCase):
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 --git a/tests/unit/test_dual.py b/tests/unit/test_dual.py
index d300c9e..04a8de9 100644
--- a/tests/unit/test_dual.py
+++ b/tests/unit/test_dual.py
@@ -25,6 +25,9 @@ class TestDual(unittest.TestCase):
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 @@ class TestDual(unittest.TestCase):
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 --git a/tests/unit/test_kx.py b/tests/unit/test_kx.py
new file mode 100644
index 0000000..f057916
--- /dev/null
+++ b/tests/unit/test_kx.py
@@ -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 --git a/tests/unit/test_public.py b/tests/unit/test_public.py
index 61de5a9..c3aa6b0 100644
--- a/tests/unit/test_public.py
+++ b/tests/unit/test_public.py
@@ -24,6 +24,8 @@ class TestPublic(unittest.TestCase):
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 @@ class TestPublic(unittest.TestCase):
self.assertNotEqual(msg, bob_ctxt)
bclear = alice_box.decrypt(bob_ctxt)
self.assertEqual(msg, bclear)
+ self.assertEqual(bob.sk_hex, bob.hex_sk())