Hello community,

here is the log from the commit of package python-libnacl for openSUSE:Factory 
checked in at 2020-03-04 09:45:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-libnacl (Old)
 and      /work/SRC/openSUSE:Factory/.python-libnacl.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-libnacl"

Wed Mar  4 09:45:25 2020 rev:19 rq:781216 version:1.7.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-libnacl/python-libnacl.changes    
2019-10-16 09:14:58.839514680 +0200
+++ /work/SRC/openSUSE:Factory/.python-libnacl.new.26092/python-libnacl.changes 
2020-03-04 09:46:05.838132479 +0100
@@ -1,0 +2,8 @@
+Tue Mar  3 13:12:32 UTC 2020 - Ondřej Súkup <[email protected]>
+
+- update to 1.7.1
+ * Bindings for kdf in libsodium
+ * Added extra key validation
+ * Add Crypto_box_easy
+
+-------------------------------------------------------------------

Old:
----
  v1.6.1.tar.gz

New:
----
  v1.7.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-libnacl.spec ++++++
--- /var/tmp/diff_new_pack.yay9kO/_old  2020-03-04 09:46:08.014133783 +0100
+++ /var/tmp/diff_new_pack.yay9kO/_new  2020-03-04 09:46:08.018133785 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-libnacl
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-libnacl
-Version:        1.6.1
+Version:        1.7.1
 Release:        0
 Summary:        Python bindings for libsodium based on ctypes
 License:        Apache-2.0

++++++ v1.6.1.tar.gz -> v1.7.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/.travis.yml 
new/libnacl-1.7.1/.travis.yml
--- old/libnacl-1.6.1/.travis.yml       2017-10-24 19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/.travis.yml       2020-01-08 17:52:48.000000000 +0100
@@ -1,21 +1,19 @@
 sudo: required
-dist: trusty
+dist: bionic
 language: python
 python:
   - "2.7"
-  - "3.3"
-  - "3.4"
   - "3.5"
-  - "pypy"
-  # disable pypy3 until it is compatible to 3.3+
-  # - "pypy3"
+  - "3.6"
+  - "3.7"
+  - "pypy2"
+  - "pypy3"
 
 install:
-  - sudo add-apt-repository -y ppa:chris-lea/libsodium
   - sudo apt-get update -qq
-  - sudo apt-get install -y libsodium13
-  - "python -m pip install -U pip setuptools"  
-  
+  - sudo apt-get install -y libsodium23
+  - "python -m pip install -U pip setuptools"
+
 script:
   - "python -m unittest discover --start-directory tests -v"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/MANIFEST.in 
new/libnacl-1.7.1/MANIFEST.in
--- old/libnacl-1.6.1/MANIFEST.in       2017-10-24 19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/MANIFEST.in       2020-01-08 17:52:48.000000000 +0100
@@ -1,6 +1,6 @@
 include LICENSE
 include AUTHORS
 include README.rst
-recursive-include tests *
+recursive-include tests *.py
 recursive-include doc *
 recursive-include pkg *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/doc/conf.py 
new/libnacl-1.7.1/doc/conf.py
--- old/libnacl-1.6.1/doc/conf.py       2017-10-24 19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/doc/conf.py       2020-01-08 17:52:48.000000000 +0100
@@ -48,7 +48,7 @@
 
 # General information about the project.
 project = u'libnacl'
-copyright = u'2017, Thomas S Hatch'
+copyright = u'2020, 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
@@ -267,7 +267,7 @@
 epub_title = u'libnacl'
 epub_author = u'Thomas S Hatch'
 epub_publisher = u'Thomas S Hatch'
-epub_copyright = u'2017, Thomas S Hatch'
+epub_copyright = u'2020, 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.6.1/doc/topics/releases/1.6.1.rst 
new/libnacl-1.7.1/doc/topics/releases/1.6.1.rst
--- old/libnacl-1.6.1/doc/topics/releases/1.6.1.rst     2017-10-24 
19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/doc/topics/releases/1.6.1.rst     2020-01-08 
17:52:48.000000000 +0100
@@ -1,5 +1,5 @@
 ===========================
-libnacl 1.6.0 Release Notes
+libnacl 1.6.1 Release Notes
 ===========================
 
 Add support for libsodium 1.0.15
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/doc/topics/releases/1.7.1.rst 
new/libnacl-1.7.1/doc/topics/releases/1.7.1.rst
--- old/libnacl-1.6.1/doc/topics/releases/1.7.1.rst     1970-01-01 
01:00:00.000000000 +0100
+++ new/libnacl-1.7.1/doc/topics/releases/1.7.1.rst     2020-01-08 
17:52:48.000000000 +0100
@@ -0,0 +1,21 @@
+===========================
+libnacl 1.7.1 Release Notes
+===========================
+
+This release fixes a few minor bugs, primarily in tests, and restores
+functionality with older versions of libsodium.
+
+Compatibility With Older libsodium
+==================================
+
+PR #118 fixes compatibility with Debian 8.
+
+Test Fixes
+==========
+
+Some unreliability in tests were found by the Debian team. These
+issues were fixed in PRs #115 and #116.
+
+Travis no longer supports the same pypy tests on all platforms,
+these were removed in PR #119.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/doc/topics/releases/1.7.rst 
new/libnacl-1.7.1/doc/topics/releases/1.7.rst
--- old/libnacl-1.6.1/doc/topics/releases/1.7.rst       1970-01-01 
01:00:00.000000000 +0100
+++ new/libnacl-1.7.1/doc/topics/releases/1.7.rst       2020-01-08 
17:52:48.000000000 +0100
@@ -0,0 +1,18 @@
+=========================
+libnacl 1.7 Release Notes
+=========================
+
+Bindings for kdf in libsodium
+=============================
+
+Thanks to Michael Mendoza, PR #109
+
+Added extra key validation
+==========================
+
+Thanks to Kent Ross, PR #106
+
+Add Crypto_box_easy
+===================
+
+Thanks to jheling PR #114
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/libnacl/__init__.py 
new/libnacl-1.7.1/libnacl/__init__.py
--- old/libnacl-1.6.1/libnacl/__init__.py       2017-10-24 19:39:28.000000000 
+0200
+++ new/libnacl-1.7.1/libnacl/__init__.py       2020-01-08 17:52:48.000000000 
+0100
@@ -80,7 +80,13 @@
             msg += 'libsodium.so.{0}, '.format(soname_ver)
         raise OSError(msg)
 
-nacl = _get_nacl()
+# Don't load libnacl if we are in sphinx
+if not 'sphinx' in sys.argv[0]:
+    nacl = _get_nacl()
+    DOC_RUN = False
+else:
+    nacl = None
+    DOC_RUN = True
 
 
 # Define exceptions
@@ -89,74 +95,101 @@
     Base Exception for cryptographic errors
     """
 
-sodium_init = nacl.sodium_init
-sodium_init.res_type = ctypes.c_int
-if sodium_init() < 0:
-    raise RuntimeError('sodium_init() call failed!')
-
-# Define constants
-try:
-    crypto_box_SEALBYTES = nacl.crypto_box_sealbytes()
-    HAS_SEAL = True
-except AttributeError:
-    HAS_SEAL = False
-try:
-    crypto_aead_aes256gcm_KEYBYTES = nacl.crypto_aead_aes256gcm_keybytes()
-    crypto_aead_aes256gcm_NPUBBYTES = nacl.crypto_aead_aes256gcm_npubbytes()
-    crypto_aead_aes256gcm_ABYTES = nacl.crypto_aead_aes256gcm_abytes()
-    HAS_AEAD_AES256GCM = bool(nacl.crypto_aead_aes256gcm_is_available())
-    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()
-    HAS_AEAD_CHACHA20POLY1305_IETF = True
-    HAS_AEAD = True
-except AttributeError:
-    HAS_AEAD_AES256GCM = False
-    HAS_AEAD_CHACHA20POLY1305_IETF = False
-    HAS_AEAD = False
-
-crypto_box_SECRETKEYBYTES = nacl.crypto_box_secretkeybytes()
-crypto_box_SEEDBYTES = nacl.crypto_box_seedbytes()
-crypto_box_PUBLICKEYBYTES = nacl.crypto_box_publickeybytes()
-crypto_box_NONCEBYTES = nacl.crypto_box_noncebytes()
-crypto_box_ZEROBYTES = nacl.crypto_box_zerobytes()
-crypto_box_BOXZEROBYTES = nacl.crypto_box_boxzerobytes()
-crypto_box_BEFORENMBYTES = nacl.crypto_box_beforenmbytes()
-crypto_scalarmult_BYTES = nacl.crypto_scalarmult_bytes()
-crypto_scalarmult_SCALARBYTES = nacl.crypto_scalarmult_scalarbytes()
-crypto_sign_BYTES = nacl.crypto_sign_bytes()
-crypto_sign_SEEDBYTES = nacl.crypto_sign_secretkeybytes() // 2
-crypto_sign_PUBLICKEYBYTES = nacl.crypto_sign_publickeybytes()
-crypto_sign_SECRETKEYBYTES = nacl.crypto_sign_secretkeybytes()
-crypto_sign_ed25519_PUBLICKEYBYTES = nacl.crypto_sign_ed25519_publickeybytes()
-crypto_sign_ed25519_SECRETKEYBYTES = nacl.crypto_sign_ed25519_secretkeybytes()
-crypto_box_MACBYTES = crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES
-crypto_secretbox_KEYBYTES = nacl.crypto_secretbox_keybytes()
-crypto_secretbox_NONCEBYTES = nacl.crypto_secretbox_noncebytes()
-crypto_secretbox_ZEROBYTES = nacl.crypto_secretbox_zerobytes()
-crypto_secretbox_BOXZEROBYTES = nacl.crypto_secretbox_boxzerobytes()
-crypto_secretbox_MACBYTES = crypto_secretbox_ZEROBYTES - 
crypto_secretbox_BOXZEROBYTES
-crypto_stream_KEYBYTES = nacl.crypto_stream_keybytes()
-crypto_stream_NONCEBYTES = nacl.crypto_stream_noncebytes()
-crypto_auth_BYTES = nacl.crypto_auth_bytes()
-crypto_auth_KEYBYTES = nacl.crypto_auth_keybytes()
-crypto_onetimeauth_BYTES = nacl.crypto_onetimeauth_bytes()
-crypto_onetimeauth_KEYBYTES = nacl.crypto_onetimeauth_keybytes()
-crypto_generichash_BYTES = nacl.crypto_generichash_bytes()
-crypto_generichash_BYTES_MIN = nacl.crypto_generichash_bytes_min()
-crypto_generichash_BYTES_MAX = nacl.crypto_generichash_bytes_max()
-crypto_generichash_KEYBYTES = nacl.crypto_generichash_keybytes()
-crypto_generichash_KEYBYTES_MIN = nacl.crypto_generichash_keybytes_min()
-crypto_generichash_KEYBYTES_MAX = nacl.crypto_generichash_keybytes_max()
-crypto_scalarmult_curve25519_BYTES = nacl.crypto_scalarmult_curve25519_bytes()
-crypto_hash_BYTES = nacl.crypto_hash_sha512_bytes()
-crypto_hash_sha256_BYTES = nacl.crypto_hash_sha256_bytes()
-crypto_hash_sha512_BYTES = nacl.crypto_hash_sha512_bytes()
-crypto_verify_16_BYTES = nacl.crypto_verify_16_bytes()
-crypto_verify_32_BYTES = nacl.crypto_verify_32_bytes()
-crypto_verify_64_BYTES = nacl.crypto_verify_64_bytes()
-# pylint: enable=C0103
+if not DOC_RUN:
+    sodium_init = nacl.sodium_init
+    sodium_init.res_type = ctypes.c_int
+    if sodium_init() < 0:
+        raise RuntimeError('sodium_init() call failed!')
+
+    # Define constants
+    try:
+        crypto_box_SEALBYTES = nacl.crypto_box_sealbytes()
+        HAS_SEAL = True
+    except AttributeError:
+        HAS_SEAL = False
+    try:
+        crypto_aead_aes256gcm_KEYBYTES = nacl.crypto_aead_aes256gcm_keybytes()
+        crypto_aead_aes256gcm_NPUBBYTES = 
nacl.crypto_aead_aes256gcm_npubbytes()
+        crypto_aead_aes256gcm_ABYTES = nacl.crypto_aead_aes256gcm_abytes()
+        HAS_AEAD_AES256GCM = bool(nacl.crypto_aead_aes256gcm_is_available())
+        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()
+        HAS_AEAD_CHACHA20POLY1305_IETF = True
+        HAS_AEAD = True
+    except AttributeError:
+        HAS_AEAD_AES256GCM = False
+        HAS_AEAD_CHACHA20POLY1305_IETF = False
+        HAS_AEAD = False
+
+    crypto_box_SECRETKEYBYTES = nacl.crypto_box_secretkeybytes()
+    crypto_box_SEEDBYTES = nacl.crypto_box_seedbytes()
+    crypto_box_PUBLICKEYBYTES = nacl.crypto_box_publickeybytes()
+    crypto_box_NONCEBYTES = nacl.crypto_box_noncebytes()
+    crypto_box_ZEROBYTES = nacl.crypto_box_zerobytes()
+    crypto_box_BOXZEROBYTES = nacl.crypto_box_boxzerobytes()
+    crypto_box_BEFORENMBYTES = nacl.crypto_box_beforenmbytes()
+    crypto_scalarmult_BYTES = nacl.crypto_scalarmult_bytes()
+    crypto_scalarmult_SCALARBYTES = nacl.crypto_scalarmult_scalarbytes()
+    crypto_sign_BYTES = nacl.crypto_sign_bytes()
+    crypto_sign_SEEDBYTES = nacl.crypto_sign_secretkeybytes() // 2
+    crypto_sign_PUBLICKEYBYTES = nacl.crypto_sign_publickeybytes()
+    crypto_sign_SECRETKEYBYTES = nacl.crypto_sign_secretkeybytes()
+    crypto_sign_ed25519_PUBLICKEYBYTES = 
nacl.crypto_sign_ed25519_publickeybytes()
+    crypto_sign_ed25519_SECRETKEYBYTES = 
nacl.crypto_sign_ed25519_secretkeybytes()
+    crypto_box_MACBYTES = crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES
+    crypto_secretbox_KEYBYTES = nacl.crypto_secretbox_keybytes()
+    crypto_secretbox_NONCEBYTES = nacl.crypto_secretbox_noncebytes()
+    crypto_secretbox_ZEROBYTES = nacl.crypto_secretbox_zerobytes()
+    crypto_secretbox_BOXZEROBYTES = nacl.crypto_secretbox_boxzerobytes()
+    crypto_secretbox_MACBYTES = crypto_secretbox_ZEROBYTES - 
crypto_secretbox_BOXZEROBYTES
+    crypto_stream_KEYBYTES = nacl.crypto_stream_keybytes()
+    crypto_stream_NONCEBYTES = nacl.crypto_stream_noncebytes()
+    crypto_auth_BYTES = nacl.crypto_auth_bytes()
+    crypto_auth_KEYBYTES = nacl.crypto_auth_keybytes()
+    crypto_onetimeauth_BYTES = nacl.crypto_onetimeauth_bytes()
+    crypto_onetimeauth_KEYBYTES = nacl.crypto_onetimeauth_keybytes()
+    crypto_generichash_BYTES = nacl.crypto_generichash_bytes()
+    crypto_generichash_BYTES_MIN = nacl.crypto_generichash_bytes_min()
+    crypto_generichash_BYTES_MAX = nacl.crypto_generichash_bytes_max()
+    crypto_generichash_KEYBYTES = nacl.crypto_generichash_keybytes()
+    crypto_generichash_KEYBYTES_MIN = nacl.crypto_generichash_keybytes_min()
+    crypto_generichash_KEYBYTES_MAX = nacl.crypto_generichash_keybytes_max()
+    crypto_scalarmult_curve25519_BYTES = 
nacl.crypto_scalarmult_curve25519_bytes()
+    crypto_hash_BYTES = nacl.crypto_hash_sha512_bytes()
+    crypto_hash_sha256_BYTES = nacl.crypto_hash_sha256_bytes()
+    crypto_hash_sha512_BYTES = nacl.crypto_hash_sha512_bytes()
+    crypto_verify_16_BYTES = nacl.crypto_verify_16_bytes()
+    crypto_verify_32_BYTES = nacl.crypto_verify_32_bytes()
+    crypto_verify_64_BYTES = nacl.crypto_verify_64_bytes()
+
+    try:
+        randombytes_SEEDBYTES = nacl.randombytes_seedbytes()
+        HAS_RAND_SEED = True
+    except AttributeError:
+        HAS_RAND_SEED = False
+
+    try:
+        crypto_kdf_PRIMITIVE = nacl.crypto_kdf_primitive()
+        crypto_kdf_BYTES_MIN = nacl.crypto_kdf_bytes_min()
+        crypto_kdf_BYTES_MAX = nacl.crypto_kdf_bytes_max()
+        crypto_kdf_CONTEXTBYTES = nacl.crypto_kdf_contextbytes()
+        crypto_kdf_KEYBYTES = nacl.crypto_kdf_keybytes()
+        HAS_CRYPT_KDF = True
+    except AttributeError:
+        HAS_CRYPT_KDF = False
+
+    try:
+        crypto_kx_PUBLICKEYBYTES = nacl.crypto_kx_publickeybytes()
+        crypto_kx_SECRETKEYBYTES = nacl.crypto_kx_secretkeybytes()
+        crypto_kx_SEEDBYTES = nacl.crypto_kx_seedbytes()
+        crypto_kx_SESSIONKEYBYTES = nacl.crypto_kx_sessionkeybytes()
+        crypto_kx_PRIMITIVE = nacl.crypto_kx_primitive()
+        HAS_CRYPT_KX = True
+    except AttributeError:
+        HAS_CRYPT_KX = False
 
+    # pylint: enable=C0103
 
 # Pubkey defs
 
@@ -187,15 +220,19 @@
 
 def crypto_scalarmult_base(sk):
     '''
-    Generate a public key from a secret key 
+    Compute and return the scalar product of a standard group element and the 
given integer.
+
+    This can be used to derive a Curve25519 public key from a Curve25519 
secret key,
+    such as for usage with crypto_box and crypto_box_seal.
     '''
     if len(sk) != crypto_box_SECRETKEYBYTES:
         raise ValueError('Invalid secret key')
     pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES)
-    nacl.crypto_scalarmult_base(pk, sk)
+    if nacl.crypto_scalarmult_base(pk, sk):
+        raise CryptError('Failed to compute scalar product')
     return pk.raw
-    
-    
+
+
 def crypto_box(msg, nonce, pk, sk):
     '''
     Using a public key and a secret key encrypt the given message. A nonce
@@ -444,6 +481,9 @@
     '''
     Extract the public key from the secret key
     '''
+    if len(sk) != crypto_sign_ed25519_SECRETKEYBYTES:
+        raise ValueError('Invalid secret key')
+
     pk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES)
     ret = nacl.crypto_sign_ed25519_sk_to_pk(pk, sk)
     if ret:
@@ -455,6 +495,9 @@
     '''
     Extract the seed from the secret key 
     '''
+    if len(sk) != crypto_sign_ed25519_SECRETKEYBYTES:
+        raise ValueError('Invalid secret key')
+
     seed = ctypes.create_string_buffer(crypto_sign_SEEDBYTES)
     ret = nacl.crypto_sign_ed25519_sk_to_seed(seed, sk)
     if ret:
@@ -466,6 +509,9 @@
     '''
     Sign the given message with the given signing key
     '''
+    if len(sk) != crypto_sign_SECRETKEYBYTES:
+        raise ValueError('Invalid secret key')
+
     sig = ctypes.create_string_buffer(len(msg) + crypto_sign_BYTES)
     slen = ctypes.pointer(ctypes.c_ulonglong())
     ret = nacl.crypto_sign(
@@ -483,6 +529,9 @@
     '''
     Return signature for the given message with the given signing key
     '''
+    if len(sk) != crypto_sign_SECRETKEYBYTES:
+        raise ValueError('Invalid secret key')
+
     sig = ctypes.create_string_buffer(crypto_sign_BYTES)
     slen = ctypes.pointer(ctypes.c_ulonglong())
     ret = nacl.crypto_sign_detached(
@@ -502,6 +551,7 @@
     '''
     if len(seed) != crypto_sign_SEEDBYTES:
         raise ValueError('Invalid Seed')
+
     sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES)
     vk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES)
 
@@ -515,6 +565,9 @@
     '''
     Verifies the signed message sig using the signer's verification key
     '''
+    if len(vk) != crypto_sign_PUBLICKEYBYTES:
+        raise ValueError('Invalid public key')
+
     msg = ctypes.create_string_buffer(len(sig))
     msglen = ctypes.c_ulonglong()
     msglenp = ctypes.pointer(msglen)
@@ -533,6 +586,11 @@
     '''
     Verifies that sig is a valid signature for the message msg using the 
signer's verification key
     '''
+    if len(sig) != crypto_sign_BYTES:
+        raise ValueError('Invalid signature')
+    if len(vk) != crypto_sign_PUBLICKEYBYTES:
+        raise ValueError('Invalid public key')
+
     ret = nacl.crypto_sign_verify_detached(
             sig,
             msg,
@@ -600,6 +658,37 @@
         raise ValueError('Failed to decrypt message')
     return msg.raw[crypto_secretbox_ZEROBYTES:]
 
+# Authenticated Symmetric Encryption improved version
+
+
+def crypto_secretbox_easy(cmessage, nonce, key):
+    if len(key) != crypto_secretbox_KEYBYTES:
+        raise ValueError('Invalid key')
+
+    if len(nonce) != crypto_secretbox_NONCEBYTES:
+        raise ValueError('Invalid nonce')
+
+    
+    ctxt = ctypes.create_string_buffer(crypto_secretbox_MACBYTES + 
len(cmessage))
+    ret = nacl.crypto_secretbox_easy(ctxt, cmessage, 
ctypes.c_ulonglong(len(cmessage)), nonce, key)
+    if ret:
+        raise ValueError('Failed to encrypt message')
+    return ctxt.raw[0:]
+
+def crypto_secretbox_open_easy(ctxt, nonce, key):
+
+    if len(key) != crypto_secretbox_KEYBYTES:
+        raise ValueError('Invalid key')
+
+    if len(nonce) != crypto_secretbox_NONCEBYTES:
+        raise ValueError('Invalid nonce')
+
+    msg = ctypes.create_string_buffer(len(ctxt))
+    ret = nacl.crypto_secretbox_open_easy(msg, ctxt, 
ctypes.c_ulonglong(len(ctxt)), nonce, key)
+    if ret:
+        raise ValueError('Failed to decrypt message')
+    return msg.raw[0:len(ctxt) - crypto_secretbox_MACBYTES]    
+
 # Authenticated Symmetric Encryption with Additional Data
 
 
@@ -748,6 +837,11 @@
     '''
     Generates a stream using the given secret key and nonce
     '''
+    if len(key) != crypto_stream_KEYBYTES:
+        raise ValueError('Invalid secret key')
+    if len(nonce) != crypto_stream_NONCEBYTES:
+        raise ValueError('Invalid nonce')
+
     stream = ctypes.create_string_buffer(slen)
     ret = nacl.crypto_stream(stream, ctypes.c_ulonglong(slen), nonce, key)
     if ret:
@@ -763,6 +857,11 @@
     plaintext (xor) the output of crypto_stream. Consequently
     crypto_stream_xor can also be used to decrypt
     '''
+    if len(key) != crypto_stream_KEYBYTES:
+        raise ValueError('Invalid secret key')
+    if len(nonce) != crypto_stream_NONCEBYTES:
+        raise ValueError('Invalid nonce')
+
     stream = ctypes.create_string_buffer(len(msg))
     ret = nacl.crypto_stream_xor(
             stream,
@@ -783,6 +882,9 @@
     Constructs a one time authentication token for the given message msg
     using a given secret key
     '''
+    if len(key) != crypto_auth_KEYBYTES:
+        raise ValueError('Invalid secret key')
+
     tok = ctypes.create_string_buffer(crypto_auth_BYTES)
     ret = nacl.crypto_auth(tok, msg, ctypes.c_ulonglong(len(msg)), key)
     if ret:
@@ -795,6 +897,11 @@
     Verifies that the given authentication token is correct for the given
     message and key
     '''
+    if len(key) != crypto_auth_KEYBYTES:
+        raise ValueError('Invalid secret key')
+    if len(tok) != crypto_auth_BYTES:
+        raise ValueError('Invalid authenticator')
+
     ret = nacl.crypto_auth_verify(tok, msg, ctypes.c_ulonglong(len(msg)), key)
     if ret:
         raise ValueError('Failed to auth msg')
@@ -919,19 +1026,6 @@
             ctypes.c_size_t(key_len))
     return hbuf.raw
 
-# scalarmult
-
-
-def crypto_scalarmult_base(n):
-    '''
-    Computes and returns the scalar product of a standard group element and an
-    integer "n".
-    '''
-    buf = ctypes.create_string_buffer(crypto_scalarmult_BYTES)
-    ret = nacl.crypto_scalarmult_base(buf, n)
-    if ret:
-        raise CryptError('Failed to compute scalar product')
-    return buf.raw
 
 # String cmp
 
@@ -946,7 +1040,8 @@
     matching prefix of string1 and string2. This often allows for easy
     timing attacks.
     '''
-    return not nacl.crypto_verify_16(string1, string2)
+    a, b, c = (len(string1) >= 16), (len(string2) >= 16), (not 
nacl.crypto_verify_16(string1, string2))
+    return a & b & c
 
 
 def crypto_verify_32(string1, string2):
@@ -959,7 +1054,8 @@
     matching prefix of string1 and string2. This often allows for easy
     timing attacks.
     '''
-    return not nacl.crypto_verify_32(string1, string2)
+    a, b, c = (len(string1) >= 32), (len(string2) >= 32), (not 
nacl.crypto_verify_32(string1, string2))
+    return a & b & c
 
 
 def crypto_verify_64(string1, string2):
@@ -972,7 +1068,8 @@
     matching prefix of string1 and string2. This often allows for easy
     timing attacks.
     '''
-    return not nacl.crypto_verify_64(string1, string2)
+    a, b, c = (len(string1) >= 64), (len(string2) >= 64), (not 
nacl.crypto_verify_64(string1, string2))
+    return a & b & c
 
 
 def bytes_eq(a, b):
@@ -1017,6 +1114,22 @@
     nacl.randombytes_buf(buf, size)
     return buf.raw
 
+def randombytes_buf_deterministic(size, seed):
+    '''
+    Returns a string of random byles of the given size for a given seed. 
+    For a given seed, this function will always output the same sequence. 
+    Size can be up to 2^70 (256 GB).
+    '''
+
+    if not HAS_RAND_SEED:
+        raise ValueError('Underlying Sodium library does not support 
randombytes_seedbytes')
+    if len(seed) != randombytes_SEEDBYTES:
+        raise ValueError('Invalid key seed')
+
+    size = int(size)
+    buf = ctypes.create_string_buffer(size)
+    nacl.randombytes_buf_deterministic(buf, size, seed)
+    return buf.raw 
 
 def randombytes_close():
     '''
@@ -1049,6 +1162,85 @@
     '''
     return nacl.randombytes_uniform(upper_bound)
 
+# Key derivation API 
+
+def crypto_kdf_keygen():
+    '''
+    Returns a string of random bytes to generate a master key
+    '''
+    if not HAS_CRYPT_KDF:
+        raise ValueError('Underlying Sodium library does not support 
crypto_kdf_keybytes')
+    size = crypto_kdf_KEYBYTES
+    buf = ctypes.create_string_buffer(size)
+    nacl.crypto_kdf_keygen(buf)
+    return buf.raw 
+
+def crypto_kdf_derive_from_key(subkey_size, subkey_id, context, master_key):
+    '''
+    Returns a subkey generated from a master key for a given subkey_id. 
+    For a given subkey_id, the subkey will always be the same string.
+    '''
+    size = int(subkey_size)
+    buf = ctypes.create_string_buffer(size)
+    nacl.crypto_kdf_derive_from_key(buf, subkey_size, subkey_id, context, 
master_key)
+    return buf.raw
+
+# Key Exchange API
+
+def crypto_kx_keypair():
+    '''
+    Generate and return a new keypair
+    '''
+    if not HAS_CRYPT_KX:
+        raise ValueError('Underlying Sodium library does not support 
crypto_kx')
+    pk = ctypes.create_string_buffer(crypto_kx_PUBLICKEYBYTES)
+    sk = ctypes.create_string_buffer(crypto_kx_SECRETKEYBYTES)
+    nacl.crypto_kx_keypair(pk, sk)
+    return pk.raw, sk.raw
+
+def crypto_kx_seed_keypair(seed):
+    '''
+    Generate and return a keypair from a key seed
+    '''
+    if not HAS_CRYPT_KX:
+        raise ValueError('Underlying Sodium library does not support 
crypto_kx')
+
+    if len(seed) != crypto_kx_SEEDBYTES:
+        raise ValueError('Invalid key seed')
+    pk = ctypes.create_string_buffer(crypto_kx_PUBLICKEYBYTES)
+    sk = ctypes.create_string_buffer(crypto_kx_SECRETKEYBYTES)
+    nacl.crypto_kx_seed_keypair(pk, sk, seed)
+    return pk.raw, sk.raw
+
+def crypto_kx_client_session_keys(client_pk, client_sk, server_pk):
+    '''
+    Computes a pair of shared keys (rx and tx) using the client's public key 
client_pk, 
+    the client's secret key client_sk and the server's public key server_pk.
+    Status returns 0 on success, or -1 if the server's public key is not 
acceptable.
+    '''
+    if not HAS_CRYPT_KX:
+        raise ValueError('Underlying Sodium library does not support 
crypto_kx')
+
+    rx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
+    tx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
+    status = nacl.crypto_kx_client_session_keys(rx, tx, client_pk, client_sk, 
server_pk)
+    return rx.raw, tx.raw, status
+
+def crypto_kx_server_session_keys(server_pk, server_sk, client_pk):
+    '''
+    Computes a pair of shared keys (rx and tx) using the server's public key 
server_pk, 
+    the server's secret key server_sk and the client's public key client_pk.
+    Status returns 0 on success, or -1 if the client's public key is not 
acceptable.
+    '''
+    if not HAS_CRYPT_KX:
+        raise ValueError('Underlying Sodium library does not support 
crypto_kx')
+
+    rx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
+    tx = ctypes.create_string_buffer(crypto_kx_SESSIONKEYBYTES)
+    status = nacl.crypto_kx_server_session_keys(rx, tx, server_pk, server_sk, 
client_pk)
+    return rx.raw, tx.raw, status
+
+
 
 # Utility functions
 
@@ -1075,28 +1267,13 @@
     return func()
 
 
-def crypto_box_seed_keypair(seed):
-    '''
-    Computes and returns the public and secret keys from the given seed
-    '''
-    if len(seed) != crypto_box_SEEDBYTES:
-        raise ValueError('Invalid Seed')
-    pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES)
-    sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES)
-
-    ret = nacl.crypto_box_seed_keypair(pk, sk, seed)
-    if ret:
-        raise CryptError('Failed to generate keypair from seed')
-    return (pk.raw, sk.raw)
-
-
 def crypto_sign_ed25519_pk_to_curve25519(ed25519_pk):
     '''
     Convert an Ed25519 public key to a Curve25519 public key
     '''
     if len(ed25519_pk) != crypto_sign_ed25519_PUBLICKEYBYTES:
-        raise ValueError('Invalid Ed25519 Key')
-    
+        raise ValueError('Invalid public key')
+
     curve25519_pk = 
ctypes.create_string_buffer(crypto_scalarmult_curve25519_BYTES)
     ret = nacl.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk)
     if ret:
@@ -1109,10 +1286,12 @@
     Convert an Ed25519 secret key to a Curve25519 secret key
     '''
     if len(ed25519_sk) != crypto_sign_ed25519_SECRETKEYBYTES:
-        raise ValueError('Invalid Ed25519 Key')
-    
+        raise ValueError('Invalid secret key')
+
     curve25519_sk = 
ctypes.create_string_buffer(crypto_scalarmult_curve25519_BYTES)
     ret = nacl.crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_sk)
     if ret:
         raise CryptError('Failed to generate Curve25519 secret key')
     return curve25519_sk.raw
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/libnacl/secret_easy.py 
new/libnacl-1.7.1/libnacl/secret_easy.py
--- old/libnacl-1.6.1/libnacl/secret_easy.py    1970-01-01 01:00:00.000000000 
+0100
+++ new/libnacl-1.7.1/libnacl/secret_easy.py    2020-01-08 17:52:48.000000000 
+0100
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+'''
+Utilities to make secret box easy encryption simple
+'''
+# Import libnacl
+import libnacl
+import libnacl.utils
+import libnacl.base
+
+
+class SecretBoxEasy(libnacl.base.BaseKey):
+    '''
+    Manage symetric encryption using the salsa20 algorithm
+    '''
+    def __init__(self, key=None):
+        if key is None:
+            key = libnacl.utils.salsa_key()
+        if len(key) != libnacl.crypto_secretbox_KEYBYTES:
+            raise ValueError('Invalid key')
+        self.sk = key
+
+    def encrypt(self, msg, nonce=None, pack_nonce=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_nonce()
+        if len(nonce) != libnacl.crypto_secretbox_NONCEBYTES:
+            raise ValueError('Invalid nonce size')
+        ctxt = libnacl.crypto_secretbox_easy(msg, nonce, self.sk)
+        if pack_nonce:
+            return nonce + ctxt
+        else:
+            return nonce, ctxt
+
+    def decrypt(self, ctxt, nonce=None):
+        '''
+        Decrypt the given message, if no nonce is given the nonce will be
+        extracted from the message
+        '''
+        if nonce is None:
+            nonce = ctxt[:libnacl.crypto_secretbox_NONCEBYTES]
+            ctxt = ctxt[libnacl.crypto_secretbox_NONCEBYTES:]
+        if len(nonce) != libnacl.crypto_secretbox_NONCEBYTES:
+            raise ValueError('Invalid nonce')
+        return libnacl.crypto_secretbox_open_easy(ctxt, nonce, self.sk)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/libnacl/version.py 
new/libnacl-1.7.1/libnacl/version.py
--- old/libnacl-1.6.1/libnacl/version.py        2017-10-24 19:39:28.000000000 
+0200
+++ new/libnacl-1.7.1/libnacl/version.py        2020-01-08 17:52:48.000000000 
+0100
@@ -1 +1 @@
-__version__ = '1.6.1'
+__version__ = '1.7.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/setup.py new/libnacl-1.7.1/setup.py
--- old/libnacl-1.6.1/setup.py  2017-10-24 19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/setup.py  2020-01-08 17:52:48.000000000 +0100
@@ -25,6 +25,8 @@
           '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',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_auth_verify.py 
new/libnacl-1.7.1/tests/unit/test_auth_verify.py
--- old/libnacl-1.6.1/tests/unit/test_auth_verify.py    2017-10-24 
19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/tests/unit/test_auth_verify.py    2020-01-08 
17:52:48.000000000 +0100
@@ -57,3 +57,46 @@
             libnacl.crypto_onetimeauth_verify(sig2, msg, key1)
         self.assertTrue('Failed to auth message' in context.exception.args)
 
+    def test_auth_rejects_wrong_lengths(self):
+        msg = b'Time is an illusion. Lunchtime doubly so.'
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_auth(msg, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
+
+    def test_auth_verify_rejects_wrong_key_lengths(self):
+        msg = b"I'd take the awe of understanding over the awe of ignorance 
any day."
+        good_key = b'This valid key is 32 bytes long.'
+        good_token = b'This token is likewise also 32B.'
+
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_auth_verify(good_token, msg, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
+
+        for bad_token in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_auth_verify(bad_token, msg, good_key)
+            self.assertEqual(context.exception.args, ('Invalid 
authenticator',))
+
+    def test_onetimeauth_rejects_wrong_lengths(self):
+        msg = b"Are the most dangerous creatures the ones that use doors or 
the ones that don't?"
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_onetimeauth(msg, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
+
+    def test_onetimeauth_verify_rejects_wrong_key_lengths(self):
+        msg = b"Of all the dogs I've known in my life, I've never seen a 
better driver."
+        good_key = b'This valid key is 32 bytes long.'
+        good_token = b'1time tokens=16B'
+
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_onetimeauth_verify(good_token, msg, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
+
+        for bad_token in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_onetimeauth_verify(bad_token, msg, good_key)
+            self.assertEqual(context.exception.args, ('Invalid 
authenticator',))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_raw_auth_sym_easy.py 
new/libnacl-1.7.1/tests/unit/test_raw_auth_sym_easy.py
--- old/libnacl-1.6.1/tests/unit/test_raw_auth_sym_easy.py      1970-01-01 
01:00:00.000000000 +0100
+++ new/libnacl-1.7.1/tests/unit/test_raw_auth_sym_easy.py      2020-01-08 
17:52:48.000000000 +0100
@@ -0,0 +1,20 @@
+# Import nacl libs
+import libnacl
+import libnacl.utils
+
+# Import python libs
+import unittest
+
+
+class TestSecretBox(unittest.TestCase):
+    '''
+    Test sign functions
+    '''
+    def test_secret_box_easy(self):
+        msg = b'Are you suggesting coconuts migrate?'
+        sk1 = libnacl.utils.salsa_key()
+        nonce1 = libnacl.utils.rand_nonce()
+        enc_msg = libnacl.crypto_secretbox_easy(msg, nonce1, sk1)
+        self.assertNotEqual(msg, enc_msg)
+        clear_msg = libnacl.crypto_secretbox_open_easy(enc_msg, nonce1, sk1)
+        self.assertEqual(msg, clear_msg)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_raw_public.py 
new/libnacl-1.7.1/tests/unit/test_raw_public.py
--- old/libnacl-1.6.1/tests/unit/test_raw_public.py     2017-10-24 
19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/tests/unit/test_raw_public.py     2020-01-08 
17:52:48.000000000 +0100
@@ -79,3 +79,13 @@
         self.assertEqual(clear_msg2, msg)
         # Check bits
         self.assertNotEqual(enc_msg, enc_msg2)
+
+    def test_scalarmult_rejects_wrong_length(self):
+        good_key = b'This valid key is 32 bytes long.'
+
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_scalarmult_base(bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
+
+        self.assertEqual(libnacl.crypto_box_PUBLICKEYBYTES, 
len(libnacl.crypto_scalarmult_base(good_key)))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_raw_random.py 
new/libnacl-1.7.1/tests/unit/test_raw_random.py
--- old/libnacl-1.6.1/tests/unit/test_raw_random.py     2017-10-24 
19:39:28.000000000 +0200
+++ new/libnacl-1.7.1/tests/unit/test_raw_random.py     2020-01-08 
17:52:48.000000000 +0100
@@ -27,3 +27,78 @@
 
         self.assertEqual(256, len(freq))
         self.assertTrue(all(freq.values()))
+
+    def test_randombytes_buf_deterministic(self):
+
+        seed = libnacl.randombytes_buf(32)
+        seed2 = libnacl.randombytes_buf(32)
+        data = libnacl.randombytes_buf_deterministic(32, seed)
+        data2 = libnacl.randombytes_buf_deterministic(32, seed)
+        data3 = libnacl.randombytes_buf_deterministic(32, seed2)
+
+        self.assertEqual(32, len(data))
+        self.assertEqual(32, len(data))
+        self.assertEqual(32, len(data))
+        self.assertEqual(data, data2)
+        self.assertNotEqual(data, data3)
+
+    def test_crypto_kdf_keygen(self):
+
+        master_key = libnacl.crypto_kdf_keygen()
+
+        freq = {x: 1 for x in master_key}
+
+        self.assertEqual(32, len(master_key))
+        self.assertTrue(all(freq.values()))
+
+    def test_crypto_kdf_derive_from_key(self):
+
+      master_key = libnacl.crypto_kdf_keygen()
+      subkey = libnacl.crypto_kdf_derive_from_key(16, 1, "Examples", 
master_key)
+      subkey2 = libnacl.crypto_kdf_derive_from_key(16, 1, "Examples", 
master_key)
+      subkey3 = libnacl.crypto_kdf_derive_from_key(16, 2, "Examples", 
master_key)
+
+      self.assertEqual(16, len(subkey))
+      self.assertEqual(16, len(subkey2))
+      self.assertEqual(16, len(subkey3))
+      self.assertEqual(subkey, subkey2)
+      self.assertNotEqual(subkey, subkey3)
+      
+    def test_crypto_kx_keypair(self):
+      pk, sk = libnacl.crypto_kx_keypair()
+      self.assertEqual(32, len(pk))
+      self.assertEqual(32, len(sk))
+
+    def test_crypto_kx_seed_keypair(self):
+      seed = libnacl.randombytes_buf(32)
+      seed2 = libnacl.randombytes_buf(32)
+      pk, sk = libnacl.crypto_kx_seed_keypair(seed)
+      pk2, sk2 = libnacl.crypto_kx_seed_keypair(seed)
+      pk3, sk3 = libnacl.crypto_kx_seed_keypair(seed2)
+
+      self.assertEqual(pk, pk2)
+      self.assertNotEqual(pk, pk3)
+      self.assertEqual(sk, sk2)
+      self.assertNotEqual(sk, sk3)
+
+    def test_crypto_kx_client_session_keys(self):
+      client_pk, client_sk = libnacl.crypto_kx_keypair()
+      server_pk, server_sk = libnacl.crypto_kx_keypair()
+      rx, tx, status = libnacl.crypto_kx_client_session_keys(client_pk, 
client_sk, server_pk)
+      rx2, tx2, status = libnacl.crypto_kx_client_session_keys(client_pk, 
client_sk, server_pk)
+  
+      self.assertEqual(32, len(rx))
+      self.assertEqual(32, len(tx))
+      self.assertEqual(rx, rx2)
+      self.assertEqual(tx, tx2)
+
+    def test_crypto_kx_server_session_keys(self):
+      client_pk, client_sk = libnacl.crypto_kx_keypair()
+      server_pk, server_sk = libnacl.crypto_kx_keypair()
+      rx, tx, status = libnacl.crypto_kx_server_session_keys(client_pk, 
client_sk, server_pk)
+      rx2, tx2, status = libnacl.crypto_kx_server_session_keys(client_pk, 
client_sk, server_pk)
+      
+      self.assertEqual(32, len(rx))
+      self.assertEqual(32, len(tx))
+      self.assertEqual(rx, rx2)
+      self.assertEqual(tx, tx2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_raw_secret_easy.py 
new/libnacl-1.7.1/tests/unit/test_raw_secret_easy.py
--- old/libnacl-1.6.1/tests/unit/test_raw_secret_easy.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/libnacl-1.7.1/tests/unit/test_raw_secret_easy.py        2020-01-08 
17:52:48.000000000 +0100
@@ -0,0 +1,33 @@
+# Import libnacl libs
+import libnacl
+import libnacl.utils
+
+# Import python libs
+import unittest
+
+
+class TestSecret(unittest.TestCase):
+    """
+    Test secret functions
+    """
+    def test_secretbox_easy(self):
+        msg = b'Are you suggesting coconuts migrate?'
+
+        nonce = libnacl.utils.rand_nonce()
+        key = libnacl.utils.salsa_key()
+
+        c = libnacl.crypto_secretbox_easy(msg, nonce, key)
+        m = libnacl.crypto_secretbox_open_easy(c, nonce, key)
+        self.assertEqual(msg, m)
+
+        with self.assertRaises(ValueError):
+            libnacl.crypto_secretbox_easy(msg, b'too_short', key)
+
+        with self.assertRaises(ValueError):
+            libnacl.crypto_secretbox_easy(msg, nonce, b'too_short')
+
+        with self.assertRaises(ValueError):
+            libnacl.crypto_secretbox_open_easy(c, b'too_short', key)
+
+        with self.assertRaises(ValueError):
+            libnacl.crypto_secretbox_open_easy(c, nonce, b'too_short')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_secret_easy.py 
new/libnacl-1.7.1/tests/unit/test_secret_easy.py
--- old/libnacl-1.6.1/tests/unit/test_secret_easy.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/libnacl-1.7.1/tests/unit/test_secret_easy.py    2020-01-08 
17:52:48.000000000 +0100
@@ -0,0 +1,22 @@
+# Import libnacl libs
+import libnacl.secret_easy
+# Import python libs
+import unittest
+
+class TestSecretEasy(unittest.TestCase):
+    '''
+    '''
+    def test_secret(self):
+        msg = b'But then of course African swallows are not migratory.'
+        box = libnacl.secret_easy.SecretBoxEasy()
+        ctxt = box.encrypt(msg)
+        self.assertNotEqual(msg, ctxt)
+        box2 = libnacl.secret_easy.SecretBoxEasy(box.sk)
+        clear1 = box.decrypt(ctxt)
+        self.assertEqual(msg, clear1)
+        clear2 = box2.decrypt(ctxt)
+        self.assertEqual(clear1, clear2)
+        ctxt2 = box2.encrypt(msg)
+        clear3 = box.decrypt(ctxt2)
+        self.assertEqual(clear3, msg)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_sign.py 
new/libnacl-1.7.1/tests/unit/test_sign.py
--- old/libnacl-1.6.1/tests/unit/test_sign.py   2017-10-24 19:39:28.000000000 
+0200
+++ new/libnacl-1.7.1/tests/unit/test_sign.py   2020-01-08 17:52:48.000000000 
+0100
@@ -21,3 +21,73 @@
         self.assertEqual(verified, msg)
         self.assertEqual(verified2, msg)
 
+    def test_key_decomposition(self):
+        prv_key = b'The two halves are understood to'
+        pub_key = b'be essentially arbitrary values.'
+        secret_key = prv_key + pub_key
+        # The following functions should simply decompose a secret key
+        # without performing real computation. libsodium understands secret
+        # keys to be (private seed bytes || derived public key bytes).
+        self.assertEqual(prv_key, 
libnacl.crypto_sign_ed25519_sk_to_seed(secret_key))
+        self.assertEqual(pub_key, 
libnacl.crypto_sign_ed25519_sk_to_pk(secret_key))
+
+    def test_key_decomposition_rejects_wrong_key_lengths(self):
+        """
+        Too few bytes in a key passed through to libsodium will lead to bytes 
past the end
+        of the string being read. We should be guarding against this dangerous 
case.
+        """
+        for test_func in (libnacl.crypto_sign_ed25519_sk_to_seed, 
libnacl.crypto_sign_ed25519_sk_to_pk):
+            for bad_key in (b'too short', b'too long' * 100):
+                with self.assertRaises(ValueError) as context:
+                    test_func(bad_key)
+                self.assertEqual(context.exception.args, ('Invalid secret 
key',))
+
+    def test_sign_rejects_wrong_key_lengths(self):
+        """
+        Too few bytes in a key passed through to libsodium will lead to bytes 
past the end
+        of the string being read. We should be guarding against this dangerous 
case.
+        """
+        msg = b'The message does not matter.'
+        for test_func in (libnacl.crypto_sign, libnacl.crypto_sign_detached):
+            for bad_key in (b'too short', b'too long' * 100):
+                with self.assertRaises(ValueError) as context:
+                    test_func(msg, bad_key)
+                self.assertEqual(context.exception.args, ('Invalid secret 
key',))
+
+    def test_open_rejects_wrong_key_lengths(self):
+        """
+        Too few bytes in a key passed through to libsodium will lead to bytes 
past the end
+        of the string being read. We should be guarding against this dangerous 
case.
+        """
+        msg = b'The message does not matter.'
+        good_key = b'This valid key is 32 bytes long.'
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_sign_open(msg, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid public key',))
+
+        with self.assertRaises(ValueError) as context:
+            libnacl.crypto_sign_open(msg, good_key)
+        self.assertEqual(context.exception.args, ('Failed to validate 
message',))
+
+    def test_verify_detached_rejects_wrong_key_lengths(self):
+        """
+        Too few bytes in a key passed through to libsodium will lead to bytes 
past the end
+        of the string being read. We should be guarding against this dangerous 
case.
+        """
+        msg = b'The message does not matter.'
+        good_signature = b'This is a valid signature; it is 64 bytes long, no 
more, no less'
+        good_key = b'This valid key is 32 bytes long.'
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_sign_verify_detached(good_signature, msg, 
bad_key)
+            self.assertEqual(context.exception.args, ('Invalid public key',))
+
+        for bad_signature in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_sign_verify_detached(bad_signature, msg, 
good_key)
+            self.assertEqual(context.exception.args, ('Invalid signature',))
+
+        with self.assertRaises(ValueError) as context:
+            libnacl.crypto_sign_verify_detached(good_signature, msg, good_key)
+        self.assertEqual(context.exception.args, ('Failed to validate 
message',))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_stream.py 
new/libnacl-1.7.1/tests/unit/test_stream.py
--- old/libnacl-1.6.1/tests/unit/test_stream.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/libnacl-1.7.1/tests/unit/test_stream.py 2020-01-08 17:52:48.000000000 
+0100
@@ -0,0 +1,43 @@
+# Import libnacl libs
+import libnacl.sign
+
+# Import pythonlibs
+import unittest
+
+
+class TestStream(unittest.TestCase):
+    def test_stream_rejects_wrong_lengths(self):
+        """
+        Too few bytes in a key or nonce passed through to libsodium will lead 
to bytes past the end
+        of the string being read. We should be guarding against this dangerous 
case.
+        """
+        msg_len = 100  # whatever
+        good_nonce= b'Nonces must be 24 bytes.'
+        good_key = b'This valid key is 32 bytes long.'
+        for bad_nonce in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_stream(msg_len, bad_nonce, good_key)
+            self.assertEqual(context.exception.args, ('Invalid nonce',))
+
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_stream(msg_len, good_nonce, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
+
+    def test_stream_xor_rejects_wrong_lengths(self):
+        """
+        Too few bytes in a key or nonce passed through to libsodium will lead 
to bytes past the end
+        of the string being read. We should be guarding against this dangerous 
case.
+        """
+        msg = b'The message does not matter.'
+        good_nonce = b'Nonces must be 24 bytes.'
+        good_key = b'This valid key is 32 bytes long.'
+        for bad_nonce in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_stream_xor(msg, bad_nonce, good_key)
+            self.assertEqual(context.exception.args, ('Invalid nonce',))
+
+        for bad_key in (b'too short', b'too long' * 100):
+            with self.assertRaises(ValueError) as context:
+                libnacl.crypto_stream_xor(msg, good_nonce, bad_key)
+            self.assertEqual(context.exception.args, ('Invalid secret key',))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libnacl-1.6.1/tests/unit/test_verify.py 
new/libnacl-1.7.1/tests/unit/test_verify.py
--- old/libnacl-1.6.1/tests/unit/test_verify.py 2017-10-24 19:39:28.000000000 
+0200
+++ new/libnacl-1.7.1/tests/unit/test_verify.py 2020-01-08 17:52:48.000000000 
+0100
@@ -14,7 +14,8 @@
         self.assertTrue(libnacl.crypto_verify_16(v16, v16x))
         self.assertTrue(libnacl.bytes_eq(v16, v16x))
         v16x = bytearray(v16x)
-        v16x[libnacl.randombytes_random() & 15] += 1
+        i = libnacl.randombytes_random() & 15
+        v16x[i] = (v16x[i] + 1) % 256
         v16x = bytes(v16x)
         self.assertFalse(libnacl.crypto_verify_16(v16, v16x))
         self.assertFalse(libnacl.bytes_eq(v16, v16x))
@@ -27,7 +28,8 @@
         self.assertTrue(libnacl.crypto_verify_32(v32, v32x))
         self.assertTrue(libnacl.bytes_eq(v32, v32x))
         v32x = bytearray(v32x)
-        v32x[libnacl.randombytes_random() & 31] += 1
+        i = libnacl.randombytes_random() & 31
+        v32x[i] = (v32x[i] + 1) % 256
         v32x = bytes(v32x)
         self.assertFalse(libnacl.crypto_verify_32(v32, v32x))
         self.assertFalse(libnacl.bytes_eq(v32, v32x))
@@ -40,7 +42,8 @@
         self.assertTrue(libnacl.crypto_verify_64(v64, v64x))
         self.assertTrue(libnacl.bytes_eq(v64, v64x))
         v64x = bytearray(v64x)
-        v64x[libnacl.randombytes_random() & 63] += 1
+        i = libnacl.randombytes_random() & 63
+        v64x[i] = (v64x[i] + 1) % 256
         v64x = bytes(v64x)
         self.assertFalse(libnacl.crypto_verify_64(v64, v64x))
         self.assertFalse(libnacl.bytes_eq(v64, v64x))
@@ -57,7 +60,7 @@
     def test_different(self):
         a = libnacl.randombytes_buf(122)
         b = bytearray(a)
-        b[87] += 1
+        b[87] = (b[87] + 1) % 256
         b = bytes(b)
         self.assertFalse(libnacl.bytes_eq(a, b))
 


Reply via email to