diff options
author | Colin Watson <cjwatson@debian.org> | 2020-11-08 16:47:14 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2020-11-08 16:47:14 +0000 |
commit | 4673cf443e807698faf7992fa275cc3aa47dd344 (patch) | |
tree | b8c445b9b9a35ff67a210068f696a9503d1fdd19 | |
parent | d9266e17907a20e05c29d6027c55eb453627a662 (diff) |
New upstream version 1.7.2
-rw-r--r-- | PKG-INFO | 2 | ||||
-rw-r--r-- | doc/conf.py | 189 | ||||
-rw-r--r-- | libnacl.egg-info/PKG-INFO | 2 | ||||
-rw-r--r-- | libnacl/__init__.py | 762 | ||||
-rw-r--r-- | libnacl/public.py | 24 | ||||
-rw-r--r-- | libnacl/utils.py | 7 | ||||
-rw-r--r-- | libnacl/version.py | 3 | ||||
-rw-r--r-- | setup.py | 50 |
8 files changed, 543 insertions, 496 deletions
@@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: libnacl -Version: 1.7.1 +Version: 1.7.2 Summary: Python bindings for libsodium based on ctypes Home-page: https://libnacl.readthedocs.org/ Author: Thomas S Hatch diff --git a/doc/conf.py b/doc/conf.py index 6d6817b..012feec 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -14,41 +14,42 @@ import sys import os -sys.path.insert(0, os.path.abspath('..')) -from libnacl import __version__ as version + +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 # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', + "sphinx.ext.autodoc", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'libnacl' -copyright = u'2020, Thomas S Hatch' +project = u"libnacl" +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 @@ -60,181 +61,175 @@ release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -#html_theme = 'default' +# html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] +# html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a <link> tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -#htmlhelp_basename = 'libnacl' +# htmlhelp_basename = 'libnacl' # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'libnacl.tex', u'libnacl Documentation', - u'Thomas S Hatch', 'manual'), + ("index", "libnacl.tex", u"libnacl Documentation", u"Thomas S Hatch", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'libnacl', u'libnacl Documentation', - [u'Thomas S Hatch'], 1) -] +man_pages = [("index", "libnacl", u"libnacl Documentation", [u"Thomas S Hatch"], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -243,89 +238,95 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'libnacl', u'libnacl Documentation', - u'Thomas S Hatch', 'libnacl', 'One line description of project.', - 'Miscellaneous'), + ( + "index", + "libnacl", + u"libnacl Documentation", + u"Thomas S Hatch", + "libnacl", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False # -- Options for Epub output ---------------------------------------------- # Bibliographic Dublin Core info. -epub_title = u'libnacl' -epub_author = u'Thomas S Hatch' -epub_publisher = u'Thomas S Hatch' -epub_copyright = u'2020, Thomas S Hatch' +epub_title = u"libnacl" +epub_author = u"Thomas S Hatch" +epub_publisher = u"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' +# epub_basename = u'libnacl' # The HTML theme for the epub output. Since the default themes are not optimized # for small screen space, using the same theme for HTML and epub output is # usually not wise. This defaults to 'epub', a theme designed to save visual # space. -#epub_theme = 'epub' +# epub_theme = 'epub' # The language of the text. It defaults to the language option # or en if the language is not set. -#epub_language = '' +# epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' +# epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. -#epub_identifier = '' +# epub_identifier = '' # A unique identification for the text. -#epub_uid = '' +# epub_uid = '' # A tuple containing the cover image and cover page html template filenames. -#epub_cover = () +# epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. -#epub_guide = () +# epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. -#epub_pre_files = [] +# epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. -#epub_post_files = [] +# epub_post_files = [] # A list of files that should not be packed into the epub file. -#epub_exclude_files = [] +# epub_exclude_files = [] # The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 +# epub_tocdepth = 3 # Allow duplicate toc entries. -#epub_tocdup = True +# epub_tocdup = True # Choose between 'default' and 'includehidden'. -#epub_tocscope = 'default' +# epub_tocscope = 'default' # Fix unsupported image types using the PIL. -#epub_fix_images = False +# epub_fix_images = False # Scale large images. -#epub_max_image_width = 0 +# epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. -#epub_show_urls = 'inline' +# epub_show_urls = 'inline' # If false, no index is generated. -#epub_use_index = True +# epub_use_index = True diff --git a/libnacl.egg-info/PKG-INFO b/libnacl.egg-info/PKG-INFO index fc8b348..fe31e64 100644 --- a/libnacl.egg-info/PKG-INFO +++ b/libnacl.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: libnacl -Version: 1.7.1 +Version: 1.7.2 Summary: Python bindings for libsodium based on ctypes Home-page: https://libnacl.readthedocs.org/ Author: Thomas S Hatch diff --git a/libnacl/__init__.py b/libnacl/__init__.py index b99d063..98a53d9 100644 --- a/libnacl/__init__.py +++ b/libnacl/__init__.py @@ -1,10 +1,8 @@ # -*- coding: utf-8 -*- -''' +""" Wrap libsodium routines -''' +""" # pylint: disable=C0103 -# Import libnacl libs -from libnacl.version import __version__ # Import python libs import ctypes import sys @@ -14,74 +12,71 @@ __SONAMES = (23, 18, 17, 13, 10, 5, 4) def _get_nacl(): - ''' + """ Locate the nacl c libs to use - ''' + """ # Import libsodium - if sys.platform.startswith('win'): + if sys.platform.startswith("win"): try: - return ctypes.cdll.LoadLibrary('libsodium') + return ctypes.cdll.LoadLibrary("libsodium") except OSError: pass for soname_ver in __SONAMES: try: - return ctypes.cdll.LoadLibrary( - 'libsodium-{0}'.format(soname_ver) - ) + return ctypes.cdll.LoadLibrary("libsodium-{0}".format(soname_ver)) except OSError: pass - msg = 'Could not locate nacl lib, searched for libsodium' + msg = "Could not locate nacl lib, searched for libsodium" raise OSError(msg) - elif sys.platform.startswith('darwin'): + elif sys.platform.startswith("darwin"): try: - return ctypes.cdll.LoadLibrary('libsodium.dylib') + return ctypes.cdll.LoadLibrary("libsodium.dylib") except OSError: pass try: - libidx = __file__.find('lib') + libidx = __file__.find("lib") if libidx > 0: - libpath = __file__[0:libidx+3] + '/libsodium.dylib' + libpath = __file__[0 : libidx + 3] + "/libsodium.dylib" return ctypes.cdll.LoadLibrary(libpath) except OSError: - msg = 'Could not locate nacl lib, searched for libsodium' + msg = "Could not locate nacl lib, searched for libsodium" raise OSError(msg) else: try: - return ctypes.cdll.LoadLibrary('libsodium.so') + return ctypes.cdll.LoadLibrary("libsodium.so") except OSError: pass try: - return ctypes.cdll.LoadLibrary('/usr/local/lib/libsodium.so') + return ctypes.cdll.LoadLibrary("/usr/local/lib/libsodium.so") except OSError: pass try: - libidx = __file__.find('lib') + libidx = __file__.find("lib") if libidx > 0: - libpath = __file__[0:libidx+3] + '/libsodium.so' + libpath = __file__[0 : libidx + 3] + "/libsodium.so" return ctypes.cdll.LoadLibrary(libpath) except OSError: pass for soname_ver in __SONAMES: try: - return ctypes.cdll.LoadLibrary( - 'libsodium.so.{0}'.format(soname_ver) - ) + return ctypes.cdll.LoadLibrary("libsodium.so.{0}".format(soname_ver)) except OSError: pass try: # fall back to shipped libsodium, trust os version first - libpath = os.path.join(os.path.dirname(__file__), 'libsodium.so') + libpath = os.path.join(os.path.dirname(__file__), "libsodium.so") return ctypes.cdll.LoadLibrary(libpath) except OSError: pass - msg = 'Could not locate nacl lib, searched for libsodium.so, ' + msg = "Could not locate nacl lib, searched for libsodium.so, " for soname_ver in __SONAMES: - msg += 'libsodium.so.{0}, '.format(soname_ver) + msg += "libsodium.so.{0}, ".format(soname_ver) raise OSError(msg) + # Don't load libnacl if we are in sphinx -if not 'sphinx' in sys.argv[0]: +if not "sphinx" in sys.argv[0]: nacl = _get_nacl() DOC_RUN = False else: @@ -95,11 +90,12 @@ class CryptError(Exception): Base Exception for cryptographic errors """ + 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!') + raise RuntimeError("sodium_init() call failed!") # Define constants try: @@ -112,9 +108,15 @@ if not DOC_RUN: 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() + 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: @@ -142,7 +144,9 @@ if not DOC_RUN: 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_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() @@ -195,11 +199,11 @@ if not DOC_RUN: def crypto_box_keypair(): - ''' + """ Generate and return a new keypair pk, sk = nacl.crypto_box_keypair() - ''' + """ pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES) sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES) nacl.crypto_box_keypair(pk, sk) @@ -207,11 +211,11 @@ def crypto_box_keypair(): def crypto_box_seed_keypair(seed): - ''' - Generate and return a keypair from a key seed - ''' + """ + Generate and return a keypair from a key seed + """ if len(seed) != crypto_box_SEEDBYTES: - raise ValueError('Invalid key seed') + raise ValueError("Invalid key seed") pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES) sk = ctypes.create_string_buffer(crypto_box_SECRETKEYBYTES) nacl.crypto_box_seed_keypair(pk, sk, seed) @@ -219,385 +223,349 @@ def crypto_box_seed_keypair(seed): def crypto_scalarmult_base(sk): - ''' + """ 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') + raise ValueError("Invalid secret key") pk = ctypes.create_string_buffer(crypto_box_PUBLICKEYBYTES) if nacl.crypto_scalarmult_base(pk, sk): - raise CryptError('Failed to compute scalar product') + 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 must also be passed in, never reuse the nonce enc_msg = nacl.crypto_box('secret message', <unique nonce>, <public key string>, <secret key string>) - ''' + """ if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if len(sk) != crypto_box_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') - pad = b'\x00' * crypto_box_ZEROBYTES + msg + raise ValueError("Invalid nonce") + pad = b"\x00" * crypto_box_ZEROBYTES + msg c = ctypes.create_string_buffer(len(pad)) ret = nacl.crypto_box(c, pad, ctypes.c_ulonglong(len(pad)), nonce, pk, sk) if ret: - raise CryptError('Unable to encrypt message') + raise CryptError("Unable to encrypt message") return c.raw[crypto_box_BOXZEROBYTES:] def crypto_box_open(ctxt, nonce, pk, sk): - ''' + """ Decrypts a message given the receiver's private key, and sender's public key - ''' + """ if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if len(sk) != crypto_box_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') - pad = b'\x00' * crypto_box_BOXZEROBYTES + ctxt + raise ValueError("Invalid nonce") + pad = b"\x00" * crypto_box_BOXZEROBYTES + ctxt msg = ctypes.create_string_buffer(len(pad)) - ret = nacl.crypto_box_open( - msg, - pad, - ctypes.c_ulonglong(len(pad)), - nonce, - pk, - sk) + ret = nacl.crypto_box_open(msg, pad, ctypes.c_ulonglong(len(pad)), nonce, pk, sk) if ret: - raise CryptError('Unable to decrypt ciphertext') + raise CryptError("Unable to decrypt ciphertext") return msg.raw[crypto_box_ZEROBYTES:] def crypto_box_easy(msg, nonce, pk, sk): - ''' + """ Using a public key and a secret key encrypt the given message. A nonce must also be passed in, never reuse the nonce enc_msg = nacl.crypto_box_easy('secret message', <unique nonce>, <public key string>, <secret key string>) - ''' + """ if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if len(sk) != crypto_box_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") c = ctypes.create_string_buffer(len(msg) + crypto_box_MACBYTES) ret = nacl.crypto_box(c, msg, ctypes.c_ulonglong(len(msg)), nonce, pk, sk) if ret: - raise CryptError('Unable to encrypt message') + raise CryptError("Unable to encrypt message") return c.raw def crypto_box_open_easy(ctxt, nonce, pk, sk): - ''' + """ Decrypts a message given the receiver's private key, and sender's public key - ''' + """ if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if len(sk) != crypto_box_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") msg = ctypes.create_string_buffer(len(ctxt) - crypto_box_MACBYTES) - ret = nacl.crypto_box_open( - msg, - ctxt, - ctypes.c_ulonglong(len(ctxt)), - nonce, - pk, - sk) + ret = nacl.crypto_box_open(msg, ctxt, ctypes.c_ulonglong(len(ctxt)), nonce, pk, sk) if ret: - raise CryptError('Unable to decrypt ciphertext') + raise CryptError("Unable to decrypt ciphertext") return msg.raw[crypto_box_ZEROBYTES:] def crypto_box_beforenm(pk, sk): - ''' + """ Partially performs the computation required for both encryption and decryption of data - ''' + """ if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if len(sk) != crypto_box_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") k = ctypes.create_string_buffer(crypto_box_BEFORENMBYTES) ret = nacl.crypto_box_beforenm(k, pk, sk) if ret: - raise CryptError('Unable to compute shared key') + raise CryptError("Unable to compute shared key") return k.raw def crypto_box_afternm(msg, nonce, k): - ''' + """ Encrypts a given a message, using partial computed data - ''' + """ if len(k) != crypto_box_BEFORENMBYTES: - raise ValueError('Invalid shared key') + raise ValueError("Invalid shared key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') - pad = b'\x00' * crypto_box_ZEROBYTES + msg + raise ValueError("Invalid nonce") + pad = b"\x00" * crypto_box_ZEROBYTES + msg ctxt = ctypes.create_string_buffer(len(pad)) ret = nacl.crypto_box_afternm(ctxt, pad, ctypes.c_ulonglong(len(pad)), nonce, k) if ret: - raise CryptError('Unable to encrypt messsage') + raise CryptError("Unable to encrypt messsage") return ctxt.raw[crypto_box_BOXZEROBYTES:] def crypto_box_open_afternm(ctxt, nonce, k): - ''' + """ Decrypts a ciphertext ctxt given k - ''' + """ if len(k) != crypto_box_BEFORENMBYTES: - raise ValueError('Invalid shared key') + raise ValueError("Invalid shared key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') - pad = b'\x00' * crypto_box_BOXZEROBYTES + ctxt + raise ValueError("Invalid nonce") + pad = b"\x00" * crypto_box_BOXZEROBYTES + ctxt msg = ctypes.create_string_buffer(len(pad)) - ret = nacl.crypto_box_open_afternm( - msg, - pad, - ctypes.c_ulonglong(len(pad)), - nonce, - k) + ret = nacl.crypto_box_open_afternm(msg, pad, ctypes.c_ulonglong(len(pad)), nonce, k) if ret: - raise CryptError('unable to decrypt message') + raise CryptError("unable to decrypt message") return msg.raw[crypto_box_ZEROBYTES:] def crypto_box_easy_afternm(msg, nonce, k): - ''' + """ Using a precalculated shared key, encrypt the given message. A nonce must also be passed in, never reuse the nonce enc_msg = nacl.crypto_box_easy_afternm('secret message', <unique nonce>, <shared key string>) - ''' + """ if len(k) != crypto_box_BEFORENMBYTES: - raise ValueError('Invalid shared key') + raise ValueError("Invalid shared key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") ctxt = ctypes.create_string_buffer(len(msg) + crypto_box_MACBYTES) - ret = nacl.crypto_box_easy_afternm(ctxt, msg, ctypes.c_ulonglong(len(msg)), nonce, k) + ret = nacl.crypto_box_easy_afternm( + ctxt, msg, ctypes.c_ulonglong(len(msg)), nonce, k + ) if ret: - raise CryptError('Unable to encrypt messsage') + raise CryptError("Unable to encrypt messsage") return ctxt.raw def crypto_box_open_easy_afternm(ctxt, nonce, k): - ''' + """ Decrypts a ciphertext ctxt given k - ''' + """ if len(k) != crypto_box_BEFORENMBYTES: - raise ValueError('Invalid shared key') + raise ValueError("Invalid shared key") if len(nonce) != crypto_box_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") msg = ctypes.create_string_buffer(len(ctxt) - crypto_box_MACBYTES) ret = nacl.crypto_box_open_easy_afternm( - msg, - ctxt, - ctypes.c_ulonglong(len(ctxt)), - nonce, - k) + msg, ctxt, ctypes.c_ulonglong(len(ctxt)), nonce, k + ) if ret: - raise CryptError('unable to decrypt message') + raise CryptError("unable to decrypt message") return msg.raw def crypto_box_seal(msg, pk): - ''' + """ Using a public key to encrypt the given message. The identity of the sender cannot be verified. enc_msg = nacl.crypto_box_seal('secret message', <public key string>) - ''' + """ if not HAS_SEAL: - raise ValueError('Underlying Sodium library does not support sealed boxes') + raise ValueError("Underlying Sodium library does not support sealed boxes") if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if not isinstance(msg, bytes): - raise TypeError('Message must be bytes') + raise TypeError("Message must be bytes") c = ctypes.create_string_buffer(len(msg) + crypto_box_SEALBYTES) ret = nacl.crypto_box_seal(c, msg, ctypes.c_ulonglong(len(msg)), pk) if ret: - raise CryptError('Unable to encrypt message') + raise CryptError("Unable to encrypt message") return c.raw def crypto_box_seal_open(ctxt, pk, sk): - ''' + """ Decrypts a message given the receiver's public and private key. - ''' + """ if not HAS_SEAL: - raise ValueError('Underlying Sodium library does not support sealed boxes') + raise ValueError("Underlying Sodium library does not support sealed boxes") if len(pk) != crypto_box_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") if len(sk) != crypto_box_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if not isinstance(ctxt, bytes): - raise TypeError('Message must be bytes') + raise TypeError("Message must be bytes") c = ctypes.create_string_buffer(len(ctxt) - crypto_box_SEALBYTES) ret = nacl.crypto_box_seal_open(c, ctxt, ctypes.c_ulonglong(len(ctxt)), pk, sk) if ret: - raise CryptError('Unable to decrypt message') + raise CryptError("Unable to decrypt message") return c.raw + # Signing functions def crypto_sign_keypair(): - ''' + """ Generates a signing/verification key pair - ''' + """ vk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES) sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES) ret = nacl.crypto_sign_keypair(vk, sk) if ret: - raise ValueError('Failed to generate keypair') + raise ValueError("Failed to generate keypair") return vk.raw, sk.raw def crypto_sign_ed25519_keypair(): - ''' + """ Generates a signing/verification Ed25519 key pair - ''' + """ vk = ctypes.create_string_buffer(crypto_sign_ed25519_PUBLICKEYBYTES) sk = ctypes.create_string_buffer(crypto_sign_ed25519_SECRETKEYBYTES) ret = nacl.crypto_sign_ed25519_keypair(vk, sk) if ret: - raise ValueError('Failed to generate keypair') + raise ValueError("Failed to generate keypair") return vk.raw, sk.raw def crypto_sign_ed25519_sk_to_pk(sk): - ''' + """ Extract the public key from the secret key - ''' + """ if len(sk) != crypto_sign_ed25519_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + 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: - raise ValueError('Failed to generate public key') + raise ValueError("Failed to generate public key") return pk.raw def crypto_sign_ed25519_sk_to_seed(sk): - ''' - Extract the seed from the secret key - ''' + """ + Extract the seed from the secret key + """ if len(sk) != crypto_sign_ed25519_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + 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: - raise ValueError('Failed to generate seed') + raise ValueError("Failed to generate seed") return seed.raw def crypto_sign(msg, sk): - ''' + """ Sign the given message with the given signing key - ''' + """ if len(sk) != crypto_sign_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + 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( - sig, - slen, - msg, - ctypes.c_ulonglong(len(msg)), - sk) + ret = nacl.crypto_sign(sig, slen, msg, ctypes.c_ulonglong(len(msg)), sk) if ret: - raise ValueError('Failed to sign message') + raise ValueError("Failed to sign message") return sig.raw def crypto_sign_detached(msg, sk): - ''' + """ Return signature for the given message with the given signing key - ''' + """ if len(sk) != crypto_sign_SECRETKEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") sig = ctypes.create_string_buffer(crypto_sign_BYTES) slen = ctypes.pointer(ctypes.c_ulonglong()) - ret = nacl.crypto_sign_detached( - sig, - slen, - msg, - ctypes.c_ulonglong(len(msg)), - sk) + ret = nacl.crypto_sign_detached(sig, slen, msg, ctypes.c_ulonglong(len(msg)), sk) if ret: - raise ValueError('Failed to sign message') - return sig.raw[:slen.contents.value] + raise ValueError("Failed to sign message") + return sig.raw[: slen.contents.value] def crypto_sign_seed_keypair(seed): - ''' + """ Computes and returns the secret and verify keys from the given seed - ''' + """ if len(seed) != crypto_sign_SEEDBYTES: - raise ValueError('Invalid Seed') + raise ValueError("Invalid Seed") sk = ctypes.create_string_buffer(crypto_sign_SECRETKEYBYTES) vk = ctypes.create_string_buffer(crypto_sign_PUBLICKEYBYTES) ret = nacl.crypto_sign_seed_keypair(vk, sk, seed) if ret: - raise CryptError('Failed to generate keypair from seed') + raise CryptError("Failed to generate keypair from seed") return (vk.raw, sk.raw) def crypto_sign_open(sig, vk): - ''' + """ Verifies the signed message sig using the signer's verification key - ''' + """ if len(vk) != crypto_sign_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") msg = ctypes.create_string_buffer(len(sig)) msglen = ctypes.c_ulonglong() msglenp = ctypes.pointer(msglen) - ret = nacl.crypto_sign_open( - msg, - msglenp, - sig, - ctypes.c_ulonglong(len(sig)), - vk) + ret = nacl.crypto_sign_open(msg, msglenp, sig, ctypes.c_ulonglong(len(sig)), vk) if ret: - raise ValueError('Failed to validate message') - return msg.raw[:msglen.value] # pylint: disable=invalid-slice-index + raise ValueError("Failed to validate message") + return msg.raw[: msglen.value] # pylint: disable=invalid-slice-index def crypto_sign_verify_detached(sig, msg, vk): - ''' + """ 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') + raise ValueError("Invalid signature") if len(vk) != crypto_sign_PUBLICKEYBYTES: - raise ValueError('Invalid public key') + raise ValueError("Invalid public key") - ret = nacl.crypto_sign_verify_detached( - sig, - msg, - ctypes.c_ulonglong(len(msg)), - vk) + ret = nacl.crypto_sign_verify_detached(sig, msg, ctypes.c_ulonglong(len(msg)), vk) if ret: - raise ValueError('Failed to validate message') + raise ValueError("Failed to validate message") return msg @@ -621,17 +589,16 @@ def crypto_secretbox(message, nonce, key): ValueError: if arguments' length is wrong or the operation has failed. """ if len(key) != crypto_secretbox_KEYBYTES: - raise ValueError('Invalid key') + raise ValueError("Invalid key") if len(nonce) != crypto_secretbox_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") - pad = b'\x00' * crypto_secretbox_ZEROBYTES + message + pad = b"\x00" * crypto_secretbox_ZEROBYTES + message ctxt = ctypes.create_string_buffer(len(pad)) - ret = nacl.crypto_secretbox( - ctxt, pad, ctypes.c_ulonglong(len(pad)), nonce, key) + ret = nacl.crypto_secretbox(ctxt, pad, ctypes.c_ulonglong(len(pad)), nonce, key) if ret: - raise ValueError('Failed to encrypt message') + raise ValueError("Failed to encrypt message") return ctxt.raw[crypto_secretbox_BOXZEROBYTES:] @@ -641,53 +608,54 @@ def crypto_secretbox_open(ctxt, nonce, key): public key """ if len(key) != crypto_secretbox_KEYBYTES: - raise ValueError('Invalid key') + raise ValueError("Invalid key") if len(nonce) != crypto_secretbox_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") - pad = b'\x00' * crypto_secretbox_BOXZEROBYTES + ctxt + pad = b"\x00" * crypto_secretbox_BOXZEROBYTES + ctxt msg = ctypes.create_string_buffer(len(pad)) - ret = nacl.crypto_secretbox_open( - msg, - pad, - ctypes.c_ulonglong(len(pad)), - nonce, - key) + ret = nacl.crypto_secretbox_open(msg, pad, ctypes.c_ulonglong(len(pad)), nonce, key) if ret: - raise ValueError('Failed to decrypt message') + 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') + raise ValueError("Invalid key") if len(nonce) != crypto_secretbox_NONCEBYTES: - raise ValueError('Invalid nonce') + 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) + ret = nacl.crypto_secretbox_easy( + ctxt, cmessage, ctypes.c_ulonglong(len(cmessage)), nonce, key + ) if ret: - raise ValueError('Failed to encrypt message') + 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') + raise ValueError("Invalid key") if len(nonce) != crypto_secretbox_NONCEBYTES: - raise ValueError('Invalid nonce') + 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) + 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] + raise ValueError("Failed to decrypt message") + return msg.raw[0 : len(ctxt) - crypto_secretbox_MACBYTES] + # Authenticated Symmetric Encryption with Additional Data @@ -710,25 +678,30 @@ def crypto_aead_aes256gcm_encrypt(message, aad, nonce, key): ValueError: if arguments' length is wrong or the operation has failed. """ if not HAS_AEAD_AES256GCM: - raise ValueError('Underlying Sodium library does not support AES256-GCM AEAD') + raise ValueError("Underlying Sodium library does not support AES256-GCM AEAD") if len(key) != crypto_aead_aes256gcm_KEYBYTES: - raise ValueError('Invalid key') + raise ValueError("Invalid key") if len(nonce) != crypto_aead_aes256gcm_NPUBBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") length = len(message) + crypto_aead_aes256gcm_ABYTES clen = ctypes.c_ulonglong() c = ctypes.create_string_buffer(length) ret = nacl.crypto_aead_aes256gcm_encrypt( - c, ctypes.pointer(clen), - message, ctypes.c_ulonglong(len(message)), - aad, ctypes.c_ulonglong(len(aad)), + c, + ctypes.pointer(clen), + message, + ctypes.c_ulonglong(len(message)), + aad, + ctypes.c_ulonglong(len(aad)), None, - nonce, key) + nonce, + key, + ) if ret: - raise ValueError('Failed to encrypt message') + raise ValueError("Failed to encrypt message") return c.raw @@ -750,25 +723,32 @@ def crypto_aead_chacha20poly1305_ietf_encrypt(message, aad, nonce, key): ValueError: if arguments' length is wrong or the operation has failed. """ if not HAS_AEAD_CHACHA20POLY1305_IETF: - raise ValueError('Underlying Sodium library does not support IETF variant of ChaCha20Poly1305 AEAD') + raise ValueError( + "Underlying Sodium library does not support IETF variant of ChaCha20Poly1305 AEAD" + ) if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: - raise ValueError('Invalid key') + raise ValueError("Invalid key") if len(nonce) != crypto_aead_chacha20poly1305_ietf_NPUBBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") length = len(message) + crypto_aead_chacha20poly1305_ietf_ABYTES clen = ctypes.c_ulonglong() c = ctypes.create_string_buffer(length) ret = nacl.crypto_aead_chacha20poly1305_ietf_encrypt( - c, ctypes.pointer(clen), - message, ctypes.c_ulonglong(len(message)), - aad, ctypes.c_ulonglong(len(aad)), + c, + ctypes.pointer(clen), + message, + ctypes.c_ulonglong(len(message)), + aad, + ctypes.c_ulonglong(len(aad)), None, - nonce, key) + nonce, + key, + ) if ret: - raise ValueError('Failed to encrypt message') + raise ValueError("Failed to encrypt message") return c.raw @@ -778,26 +758,31 @@ def crypto_aead_aes256gcm_decrypt(ctxt, aad, nonce, key): or ciphertext were altered then the decryption will fail. """ if not HAS_AEAD_AES256GCM: - raise ValueError('Underlying Sodium library does not support AES256-GCM AEAD') + raise ValueError("Underlying Sodium library does not support AES256-GCM AEAD") if len(key) != crypto_aead_aes256gcm_KEYBYTES: - raise ValueError('Invalid key') + raise ValueError("Invalid key") if len(nonce) != crypto_aead_aes256gcm_NPUBBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") - length = len(ctxt)-crypto_aead_aes256gcm_ABYTES + length = len(ctxt) - crypto_aead_aes256gcm_ABYTES mlen = ctypes.c_ulonglong() m = ctypes.create_string_buffer(length) ret = nacl.crypto_aead_aes256gcm_decrypt( - m, ctypes.byref(mlen), + m, + ctypes.byref(mlen), None, - ctxt, ctypes.c_ulonglong(len(ctxt)), - aad, ctypes.c_ulonglong(len(aad)), - nonce, key) + ctxt, + ctypes.c_ulonglong(len(ctxt)), + aad, + ctypes.c_ulonglong(len(aad)), + nonce, + key, + ) if ret: - raise ValueError('Failed to decrypt message') + raise ValueError("Failed to decrypt message") return m.raw @@ -807,26 +792,33 @@ def crypto_aead_chacha20poly1305_ietf_decrypt(ctxt, aad, nonce, key): 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') + raise ValueError( + "Underlying Sodium library does not support IETF variant of ChaCha20Poly1305 AEAD" + ) if len(key) != crypto_aead_chacha20poly1305_ietf_KEYBYTES: - raise ValueError('Invalid key') + raise ValueError("Invalid key") if len(nonce) != crypto_aead_chacha20poly1305_ietf_NPUBBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") - length = len(ctxt)-crypto_aead_chacha20poly1305_ietf_ABYTES + length = len(ctxt) - crypto_aead_chacha20poly1305_ietf_ABYTES mlen = ctypes.c_ulonglong() m = ctypes.create_string_buffer(length) ret = nacl.crypto_aead_chacha20poly1305_ietf_decrypt( - m, ctypes.byref(mlen), + m, + ctypes.byref(mlen), None, - ctxt, ctypes.c_ulonglong(len(ctxt)), - aad, ctypes.c_ulonglong(len(aad)), - nonce, key) + ctxt, + ctypes.c_ulonglong(len(ctxt)), + aad, + ctypes.c_ulonglong(len(aad)), + nonce, + key, + ) if ret: - raise ValueError('Failed to decrypt message') + raise ValueError("Failed to decrypt message") return m.raw @@ -834,43 +826,38 @@ def crypto_aead_chacha20poly1305_ietf_decrypt(ctxt, aad, nonce, key): def crypto_stream(slen, nonce, key): - ''' + """ Generates a stream using the given secret key and nonce - ''' + """ if len(key) != crypto_stream_KEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if len(nonce) != crypto_stream_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") stream = ctypes.create_string_buffer(slen) ret = nacl.crypto_stream(stream, ctypes.c_ulonglong(slen), nonce, key) if ret: - raise ValueError('Failed to init stream') + raise ValueError("Failed to init stream") return stream.raw def crypto_stream_xor(msg, nonce, key): - ''' + """ Encrypts the given message using the given secret key and nonce The crypto_stream_xor function guarantees that the ciphertext is the 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') + raise ValueError("Invalid secret key") if len(nonce) != crypto_stream_NONCEBYTES: - raise ValueError('Invalid nonce') + raise ValueError("Invalid nonce") stream = ctypes.create_string_buffer(len(msg)) - ret = nacl.crypto_stream_xor( - stream, - msg, - ctypes.c_ulonglong(len(msg)), - nonce, - key) + ret = nacl.crypto_stream_xor(stream, msg, ctypes.c_ulonglong(len(msg)), nonce, key) if ret: - raise ValueError('Failed to init stream') + raise ValueError("Failed to init stream") return stream.raw @@ -878,35 +865,36 @@ def crypto_stream_xor(msg, nonce, key): def crypto_auth(msg, key): - ''' + """ 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') + 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: - raise ValueError('Failed to auth msg') + raise ValueError("Failed to auth msg") return tok.raw[:crypto_auth_BYTES] def crypto_auth_verify(tok, msg, key): - ''' + """ 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') + raise ValueError("Invalid secret key") if len(tok) != crypto_auth_BYTES: - raise ValueError('Invalid authenticator') + 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') + raise ValueError("Failed to auth msg") return msg + # One time authentication @@ -938,12 +926,11 @@ def crypto_onetimeauth(message, key): ValueError: if arguments' length is wrong. """ if len(key) != crypto_onetimeauth_KEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") tok = ctypes.create_string_buffer(crypto_onetimeauth_BYTES) # cannot fail - _ = nacl.crypto_onetimeauth( - tok, message, ctypes.c_ulonglong(len(message)), key) + _ = nacl.crypto_onetimeauth(tok, message, ctypes.c_ulonglong(len(message)), key) return tok.raw[:crypto_onetimeauth_BYTES] @@ -966,64 +953,68 @@ def crypto_onetimeauth_verify(token, message, key): ValueError: if arguments' length is wrong or verification has failed. """ if len(key) != crypto_onetimeauth_KEYBYTES: - raise ValueError('Invalid secret key') + raise ValueError("Invalid secret key") if len(token) != crypto_onetimeauth_BYTES: - raise ValueError('Invalid authenticator') + raise ValueError("Invalid authenticator") ret = nacl.crypto_onetimeauth_verify( - token, message, ctypes.c_ulonglong(len(message)), key) + token, message, ctypes.c_ulonglong(len(message)), key + ) if ret: - raise ValueError('Failed to auth message') + raise ValueError("Failed to auth message") return message + # Hashing def crypto_hash(msg): - ''' + """ Compute a hash of the given message - ''' + """ hbuf = ctypes.create_string_buffer(crypto_hash_BYTES) nacl.crypto_hash(hbuf, msg, ctypes.c_ulonglong(len(msg))) return hbuf.raw def crypto_hash_sha256(msg): - ''' + """ Compute the sha256 hash of the given message - ''' + """ hbuf = ctypes.create_string_buffer(crypto_hash_sha256_BYTES) nacl.crypto_hash_sha256(hbuf, msg, ctypes.c_ulonglong(len(msg))) return hbuf.raw def crypto_hash_sha512(msg): - ''' + """ Compute the sha512 hash of the given message - ''' + """ hbuf = ctypes.create_string_buffer(crypto_hash_sha512_BYTES) nacl.crypto_hash_sha512(hbuf, msg, ctypes.c_ulonglong(len(msg))) return hbuf.raw + # Generic Hash def crypto_generichash(msg, key=None): - ''' + """ Compute the blake2 hash of the given message with a given key - ''' + """ hbuf = ctypes.create_string_buffer(crypto_generichash_BYTES) if key: key_len = len(key) else: key_len = 0 nacl.crypto_generichash( - hbuf, - ctypes.c_size_t(len(hbuf)), - msg, - ctypes.c_ulonglong(len(msg)), - key, - ctypes.c_size_t(key_len)) + hbuf, + ctypes.c_size_t(len(hbuf)), + msg, + ctypes.c_ulonglong(len(msg)), + key, + ctypes.c_size_t(key_len), + ) return hbuf.raw @@ -1031,7 +1022,7 @@ def crypto_generichash(msg, key=None): def crypto_verify_16(string1, string2): - ''' + """ Compares the first crypto_verify_16_BYTES of the given strings The time taken by the function is independent of the contents of string1 @@ -1039,13 +1030,17 @@ def crypto_verify_16(string1, string2): memcmp(string1,string2,16) takes time that is dependent on the longest matching prefix of string1 and string2. This often allows for easy timing attacks. - ''' - a, b, c = (len(string1) >= 16), (len(string2) >= 16), (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): - ''' + """ Compares the first crypto_verify_32_BYTES of the given strings The time taken by the function is independent of the contents of string1 @@ -1053,13 +1048,17 @@ def crypto_verify_32(string1, string2): memcmp(string1,string2,32) takes time that is dependent on the longest matching prefix of string1 and string2. This often allows for easy timing attacks. - ''' - a, b, c = (len(string1) >= 32), (len(string2) >= 32), (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): - ''' + """ Compares the first crypto_verify_64_BYTES of the given strings The time taken by the function is independent of the contents of string1 @@ -1067,13 +1066,17 @@ def crypto_verify_64(string1, string2): memcmp(string1,string2,64) takes time that is dependent on the longest matching prefix of string1 and string2. This often allows for easy timing attacks. - ''' - a, b, c = (len(string1) >= 64), (len(string2) >= 64), (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): - ''' + """ Compares two byte instances with one another. If `a` and `b` have different lengths, return `False` immediately. Otherwise `a` and `b` will be compared in constant time. @@ -1082,9 +1085,9 @@ def bytes_eq(a, b): Raises :exc:`TypeError` in case `a` and `b` are not both of the type :class:`bytes`. - ''' + """ if not isinstance(a, bytes) or not isinstance(b, bytes): - raise TypeError('Both arguments must be bytes.') + raise TypeError("Both arguments must be bytes.") len_a = len(a) len_b = len(b) @@ -1093,147 +1096,162 @@ def bytes_eq(a, b): return nacl.sodium_memcmp(a, b, len_a) == 0 + # Random byte generation def randombytes(size): - ''' + """ Return a string of random bytes of the given size - ''' + """ buf = ctypes.create_string_buffer(size) nacl.randombytes(buf, ctypes.c_ulonglong(size)) return buf.raw def randombytes_buf(size): - ''' + """ Return a string of random bytes of the given size - ''' + """ size = int(size) buf = ctypes.create_string_buffer(size) 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. + """ + 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') + raise ValueError( + "Underlying Sodium library does not support randombytes_seedbytes" + ) if len(seed) != randombytes_SEEDBYTES: - raise ValueError('Invalid key seed') + raise ValueError("Invalid key seed") size = int(size) buf = ctypes.create_string_buffer(size) nacl.randombytes_buf_deterministic(buf, size, seed) - return buf.raw + return buf.raw + def randombytes_close(): - ''' + """ Close the file descriptor or the handle for the cryptographic service provider - ''' + """ nacl.randombytes_close() def randombytes_random(): - ''' + """ Return a random 32-bit unsigned value - ''' + """ return nacl.randombytes_random() def randombytes_stir(): - ''' + """ Generate a new key for the pseudorandom number generator The file descriptor for the entropy source is kept open, so that the generator can be reseeded even in a chroot() jail. - ''' + """ nacl.randombytes_stir() def randombytes_uniform(upper_bound): - ''' + """ Return a value between 0 and upper_bound using a uniform distribution - ''' + """ return nacl.randombytes_uniform(upper_bound) -# Key derivation API + +# 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') + 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 + 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. + """ + 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') + 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') + raise ValueError("Underlying Sodium library does not support crypto_kx") if len(seed) != crypto_kx_SEEDBYTES: - raise ValueError('Invalid key seed') + 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, + """ + 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') + 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, + """ + 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') + 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) @@ -1241,57 +1259,55 @@ def crypto_kx_server_session_keys(server_pk, server_sk, client_pk): return rx.raw, tx.raw, status - # Utility functions + def sodium_library_version_major(): - ''' + """ Return the major version number - ''' + """ return nacl.sodium_library_version_major() def sodium_library_version_minor(): - ''' + """ Return the minor version number - ''' + """ return nacl.sodium_library_version_minor() def sodium_version_string(): - ''' + """ Return the version string - ''' + """ func = nacl.sodium_version_string func.restype = ctypes.c_char_p return func() 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 public 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: - raise CryptError('Failed to generate Curve25519 public key') + raise CryptError("Failed to generate Curve25519 public key") return curve25519_pk.raw def crypto_sign_ed25519_sk_to_curve25519(ed25519_sk): - ''' + """ Convert an Ed25519 secret key to a Curve25519 secret key - ''' + """ if len(ed25519_sk) != crypto_sign_ed25519_SECRETKEYBYTES: - raise ValueError('Invalid secret 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') + raise CryptError("Failed to generate Curve25519 secret key") return curve25519_sk.raw - - diff --git a/libnacl/public.py b/libnacl/public.py index 16da4f4..bac8609 100644 --- a/libnacl/public.py +++ b/libnacl/public.py @@ -20,6 +20,18 @@ class PublicKey(libnacl.base.BaseKey): else: raise ValueError('Passed in invalid public key') + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.pk == other.pk + else: + return False + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self.pk) + class SecretKey(libnacl.base.BaseKey): ''' @@ -37,6 +49,18 @@ class SecretKey(libnacl.base.BaseKey): else: raise ValueError('Passed in invalid secret key') + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.sk == other.sk and self.pk == other.pk + else: + return False + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash((self.sk, self.pk)) + class Box(object): ''' diff --git a/libnacl/utils.py b/libnacl/utils.py index 412d518..e06e078 100644 --- a/libnacl/utils.py +++ b/libnacl/utils.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import struct +import sys import time # Import nacl libs @@ -31,7 +32,10 @@ def load_key(path_or_file, serial='json'): key_data = msgpack.load(stream) elif serial == 'json': import json - key_data = json.loads(stream.read(), encoding='UTF-8') + if sys.version_info[0] >= 3: + key_data = json.loads(stream.read()) + else: + key_data = json.loads(stream.read(), encoding='UTF-8') finally: if stream != path_or_file: stream.close() @@ -95,4 +99,3 @@ def time_nonce(): ''' nonce = rand_nonce() return (struct.pack('=d', time.time()) + nonce)[:len(nonce)] - diff --git a/libnacl/version.py b/libnacl/version.py index 48c2f6b..5dd74fc 100644 --- a/libnacl/version.py +++ b/libnacl/version.py @@ -1 +1,2 @@ -__version__ = '1.7.1' +# -*- coding: utf-8 -*- +version = "1.7.2" @@ -3,32 +3,34 @@ from setuptools import setup -NAME = 'libnacl' -DESC = 'Python bindings for libsodium based on ctypes' +NAME = "libnacl" +DESC = "Python bindings for libsodium based on ctypes" # Version info -- read without importing _locals = {} -with open('libnacl/version.py') as fp: +with open("libnacl/version.py") as fp: exec(fp.read(), None, _locals) -VERSION = _locals['__version__'] +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']) +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"], +) |