diff --git a/setup.py b/setup.py index d211d35038ded12bbaf66295c333cba1ef912933..85865081f1882bc820fad88eb3d08685af84499c 100644 --- a/setup.py +++ b/setup.py @@ -62,13 +62,13 @@ def which(name, flags=os.X_OK): # Taken from twisted sys.path += glob.glob("*.egg") try: - import nacl.nacl + import nacl._lib except ImportError: # installing - there is no cffi yet ext_modules = [] else: # building bdist - cffi is here! - ext_modules = [nacl.nacl.ffi.verifier.get_extension()] + ext_modules = [nacl._lib.ffi.verifier.get_extension()] def use_system(): @@ -210,6 +210,7 @@ setup( package_dir={"": "src"}, packages=[ "nacl", + "nacl._lib", "nacl.c", ], diff --git a/src/nacl/c/lib/__init__.py b/src/nacl/_lib/__init__.py similarity index 98% rename from src/nacl/c/lib/__init__.py rename to src/nacl/_lib/__init__.py index 31505cc9cfe5270c15efe6338ffb360a3c6dac4c..a54eb05744dee3033dc8458514f10802dc9637c0 100644 --- a/src/nacl/c/lib/__init__.py +++ b/src/nacl/_lib/__init__.py @@ -52,7 +52,7 @@ lib = ffi.verify( libraries=["sodium"], # Our ext_package is nacl so look for it - ext_package="nacl.c.lib", + ext_package="nacl.c._lib", ) diff --git a/src/nacl/c/lib/crypto_box.h b/src/nacl/_lib/crypto_box.h similarity index 70% rename from src/nacl/c/lib/crypto_box.h rename to src/nacl/_lib/crypto_box.h index 271bb7dbac123b32a1813c67f09bac741c898b71..e7d59f76386f5e6fda65332418d35e9f80ff6f21 100644 --- a/src/nacl/c/lib/crypto_box.h +++ b/src/nacl/_lib/crypto_box.h @@ -15,10 +15,10 @@ size_t crypto_box_secretkeybytes(); size_t crypto_box_publickeybytes(); - size_t crypto_box_zerobytes(); size_t crypto_box_boxzerobytes(); size_t crypto_box_noncebytes(); +size_t crypto_box_beforenmbytes(); int crypto_box_keypair(unsigned char *pk, unsigned char *sk); @@ -30,3 +30,14 @@ int crypto_box(unsigned char *c, const unsigned char *m, int crypto_box_open(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *pk, const unsigned char *sk); + +int crypto_box_beforenm(unsigned char *k, const unsigned char *pk, + const unsigned char *sk); + +int crypto_box_afternm(unsigned char *c, const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k); + +int crypto_box_open_afternm(unsigned char *m, const unsigned char *c, + unsigned long long clen, const unsigned char *n, + const unsigned char *k); diff --git a/src/nacl/_lib/crypto_scalarmult.h b/src/nacl/_lib/crypto_scalarmult.h new file mode 100644 index 0000000000000000000000000000000000000000..dee5e84928e2f2271df849d898f5a2d4bc4ab138 --- /dev/null +++ b/src/nacl/_lib/crypto_scalarmult.h @@ -0,0 +1,19 @@ +/* Copyright 2013 Donald Stufft and individual contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +size_t crypto_scalarmult_bytes(); +size_t crypto_scalarmult_scalarbytes(); + +int crypto_scalarmult_base(unsigned char *q, const unsigned char *n); diff --git a/src/nacl/c/__init__.py b/src/nacl/c/__init__.py index 09b02c6189107402d5c19123b7fbddcb0e7d48ee..e9ef7f97121c25b062b83db3b13489d1df465a09 100644 --- a/src/nacl/c/__init__.py +++ b/src/nacl/c/__init__.py @@ -13,9 +13,33 @@ # limitations under the License. from __future__ import absolute_import, division, print_function -from nacl.c.crypto_box import crypto_box_keypair +from nacl.c.crypto_box import ( + crypto_box_SECRETKEYBYTES, crypto_box_PUBLICKEYBYTES, + crypto_box_NONCEBYTES, crypto_box_ZEROBYTES, crypto_box_BOXZEROBYTES, + crypto_box_BEFORENMBYTES, crypto_box_keypair, crypto_box, crypto_box_open, + crypto_box_beforenm, crypto_box_afternm, crypto_box_open_afternm, +) +from nacl.c.crypto_scalarmult import ( + crypto_scalarmult_BYTES, crypto_scalarmult_SCALARBYTES, + crypto_scalarmult_base, +) __all__ = [ + "crypto_box_SECRETKEYBYTES", + "crypto_box_PUBLICKEYBYTES", + "crypto_box_NONCEBYTES", + "crypto_box_ZEROBYTES", + "crypto_box_BOXZEROBYTES", + "crypto_box_BEFORENMBYTES", "crypto_box_keypair", + "crypto_box", + "crypto_box_open", + "crypto_box_beforenm", + "crypto_box_afternm", + "crypto_box_open_afternm", + + "crypto_scalarmult_BYTES", + "crypto_scalarmult_SCALARBYTES", + "crypto_scalarmult_base", ] diff --git a/src/nacl/c/_lib.py b/src/nacl/c/_lib.py deleted file mode 100644 index a82ed815116433bb40a8309a25eb05a5f2544209..0000000000000000000000000000000000000000 --- a/src/nacl/c/_lib.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright 2013 Donald Stufft and individual contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import absolute_import -from __future__ import division - -import functools - -# We need to patch cffi before importing it -from nacl import _cffi_fix - -import cffi.verifier - -from cffi import FFI - - -__all__ = ["ffi", "lib"] - - -ffi = FFI() -ffi.cdef( - # Secret Key Encryption - """ - static const int crypto_secretbox_KEYBYTES; - static const int crypto_secretbox_NONCEBYTES; - static const int crypto_secretbox_ZEROBYTES; - static const int crypto_secretbox_BOXZEROBYTES; - - int crypto_secretbox(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k); - int crypto_secretbox_open(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k); - """ - - # Public Key Encryption - Signatures - """ - static const int crypto_sign_PUBLICKEYBYTES; - static const int crypto_sign_SECRETKEYBYTES; - static const int crypto_sign_BYTES; - - int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, unsigned char *seed); - int crypto_sign(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk); - int crypto_sign_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); - """ - - # Public Key Encryption - """ - static const int crypto_box_PUBLICKEYBYTES; - static const int crypto_box_SECRETKEYBYTES; - static const int crypto_box_BEFORENMBYTES; - static const int crypto_box_NONCEBYTES; - static const int crypto_box_ZEROBYTES; - static const int crypto_box_BOXZEROBYTES; - - int crypto_box_keypair(unsigned char *pk, unsigned char *sk); - int crypto_box_afternm(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k); - int crypto_box_open_afternm(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k); - int crypto_box_beforenm(unsigned char *k, const unsigned char *pk, const unsigned char *sk); - """ - - # Hashing - """ - static const int crypto_hash_BYTES; - static const int crypto_hash_sha256_BYTES; - static const int crypto_hash_sha512_BYTES; - - int crypto_hash(unsigned char *out, const unsigned char *in, unsigned long long inlen); - int crypto_hash_sha256(unsigned char *out, const unsigned char *in, unsigned long long inlen); - int crypto_hash_sha512(unsigned char *out, const unsigned char *in, unsigned long long inlen); - """ - - # Secure Random - """ - void randombytes(unsigned char * const buf, const unsigned long long buf_len); - """ - - # Low Level - Scalar Multiplication - """ - int crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n); - """ -) - - -ffi.verifier = cffi.verifier.Verifier(ffi, - "#include <sodium.h>", - - # We need to link to the sodium library - libraries=["sodium"], - - # Our ext_package is nacl so look for it - ext_package="nacl", -) - - -# This works around a bug in PyPy where CFFI exposed functions do not have a -# __name__ attribute. See https://bugs.pypy.org/issue1452 -def wraps(wrapped): - def inner(func): - if hasattr(wrapped, "__name__"): - return functools.wraps(wrapped)(func) - else: - return func - return inner - - -# A lot of the functions in nacl return 0 for success and a negative integer -# for failure. This is inconvenient in Python as 0 is a falsey value while -# negative integers are truthy. This wrapper has them return True/False as -# you'd expect in Python -def wrap_nacl_function(func): - @wraps(func) - def wrapper(*args, **kwargs): - ret = func(*args, **kwargs) - return ret == 0 - return wrapper - - -class Library(object): - - wrap = [ - "crypto_secretbox", - "crypto_secretbox_open", - - "crypto_sign_seed_keypair", - "crypto_sign", - "crypto_sign_open", - - "crypto_box_keypair", - "crypto_box_afternm", - "crypto_box_open_afternm", - "crypto_box_beforenm", - - "crypto_hash", - "crypto_hash_sha256", - "crypto_hash_sha512", - - "crypto_scalarmult_curve25519_base", - ] - - def __init__(self, ffi): - self._ffi = ffi - self._initalized = False - - # This prevents the compile_module() from being called, the module - # should have been compiled by setup.py - def _compile_module(*args, **kwargs): - raise RuntimeError("Cannot compile module during runtime") - self._ffi.verifier.compile_module = _compile_module - - def __getattr__(self, name): - if not self._initalized: - self._lib = self._ffi.verifier.load_library() - - # redirect attribute access to the underlying lib - attr = getattr(self._lib, name) - - # If this is a function that we're wrapping do the actual wrapping - if name in self.wrap: - attr = wrap_nacl_function(attr) - - # Go ahead and assign the returned value to this class so we don't - # need to do this lookup again - setattr(self, name, attr) - - return attr - -lib = Library(ffi) diff --git a/src/nacl/c/crypto_box.py b/src/nacl/c/crypto_box.py index 3a47a0dc40cb51ff6af689237796e95532becfec..57ba5ad2f97eaab67da5fcc24a23d4704e6a19e4 100644 --- a/src/nacl/c/crypto_box.py +++ b/src/nacl/c/crypto_box.py @@ -13,29 +13,37 @@ # limitations under the License. from __future__ import absolute_import, division, print_function -from nacl.c import lib +from nacl import _lib as lib from nacl.exceptions import CryptoError __all__ = ["crypto_box_keypair", "crypto_box"] +crypto_box_SECRETKEYBYTES = lib.crypto_box_secretkeybytes() +crypto_box_PUBLICKEYBYTES = lib.crypto_box_publickeybytes() +crypto_box_NONCEBYTES = lib.crypto_box_noncebytes() +crypto_box_ZEROBYTES = lib.crypto_box_zerobytes() +crypto_box_BOXZEROBYTES = lib.crypto_box_boxzerobytes() +crypto_box_BEFORENMBYTES = lib.crypto_box_beforenmbytes() + + def crypto_box_keypair(): """ Returns a randomly generated secret and public key. :rtype: (bytes(secret_key), bytes(public_key)) """ - sk_size = lib.crypto_box_secretkeybytes() - pk_size = lib.crypto_box_publickeybytes() - - sk = lib.ffi.new("unsigned char[]", sk_size) - pk = lib.ffi.new("unsigned char[]", pk_size) + sk = lib.ffi.new("unsigned char[]", crypto_box_SECRETKEYBYTES) + pk = lib.ffi.new("unsigned char[]", crypto_box_PUBLICKEYBYTES) if lib.crypto_box_keypair(pk, sk) != 0: raise CryptoError("An error occurred trying to generate the keypair") - return (lib.ffi.buffer(sk, sk_size)[:], lib.ffi.buffer(pk, pk_size)[:]) + return ( + lib.ffi.buffer(sk, crypto_box_SECRETKEYBYTES)[:], + lib.ffi.buffer(pk, crypto_box_PUBLICKEYBYTES)[:], + ) def crypto_box(sk, pk, message, nonce): @@ -49,28 +57,22 @@ def crypto_box(sk, pk, message, nonce): :param nonce: bytes :rtype: bytes """ - sk_size = lib.crypto_box_secretkeybytes() - pk_size = lib.crypto_box_publickeybytes() - n_size = lib.crypto_box_noncebytes() - zero_bytes = lib.crypto_box_zerobytes() - box_zeros = lib.crypto_box_boxzerobytes() - - if len(sk) != sk_size: + if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("Invalid secret key") - if len(pk) != pk_size: + if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("Invalid public key") - if len(nonce) != n_size: + if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("Invalid nonce size") - padded = (b"\x00" * zero_bytes) + message + padded = (b"\x00" * crypto_box_ZEROBYTES) + message ciphertext = lib.ffi.new("unsigned char[]", len(padded)) - if lib.crypto_box(ciphertext, message, len(message), nonce, pk, sk) != 0: + if lib.crypto_box(ciphertext, padded, len(padded), nonce, pk, sk) != 0: raise CryptoError("An error occurred trying to encrypt the message") - return lib.ffi.buffer(ciphertext, len(padded))[box_zeros:] + return lib.ffi.buffer(ciphertext, len(padded))[crypto_box_BOXZEROBYTES:] def crypto_box_open(sk, pk, ciphertext, nonce): @@ -84,26 +86,94 @@ def crypto_box_open(sk, pk, ciphertext, nonce): :param nonce: bytes :rtype: bytes """ - sk_size = lib.crypto_box_secretkeybytes() - pk_size = lib.crypto_box_publickeybytes() - n_size = lib.crypto_box_noncebytes() - box_zeros = lib.crypto_box_boxzerobytes() - zero_bytes = lib.crypto_box_zerobytes() - - if len(sk) != sk_size: + if len(sk) != crypto_box_SECRETKEYBYTES: raise ValueError("Invalid secret key") - if len(pk) != pk_size: + if len(pk) != crypto_box_PUBLICKEYBYTES: raise ValueError("Invalid public key") - if len(nonce) != n_size: + if len(nonce) != crypto_box_NONCEBYTES: raise ValueError("Invalid nonce size") - padded = (b"\x00" * box_zeros) + ciphertext + padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext + plaintext = lib.ffi.new("unsigned char[]", len(padded)) + + if lib.crypto_box_open(plaintext, padded, len(padded), nonce, pk, sk) != 0: + raise CryptoError("An error occurred trying to decrypt the message") + + return lib.ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:] + + +def crypto_box_beforenm(sk, pk): + """ + Computes and returns the shared key for the secret key ``sk`` and the + public key ``pk``. This can be used to speed up operations where the same + set of keys is going to be used multiple times. + + :param sk: bytes + :param pk: bytes + :rtype: bytes + """ + if len(sk) != crypto_box_SECRETKEYBYTES: + raise ValueError("Invalid secret key") + + if len(pk) != crypto_box_PUBLICKEYBYTES: + raise ValueError("Invalid public key") + + k = lib.ffi.new("unsigned char[]", crypto_box_BEFORENMBYTES) + + if lib.crypto_box_beforenm(k, pk, sk) != 0: + raise CryptoError("An error occurred computing the shared key.") + + return lib.ffi.buffer(k, crypto_box_BEFORENMBYTES)[:] + + +def crypto_box_afternm(k, message, nonce): + """ + Encrypts and returns the message ``message`` using the shared key ``k`` and + the nonce ``nonce``. + + :param k: bytes + :param message: bytes + :param nonce: bytes + :rtype: bytes + """ + if len(k) != crypto_box_BEFORENMBYTES: + raise ValueError("Invalid shared key") + + if len(nonce) != crypto_box_NONCEBYTES: + raise ValueError("Invalid nonce") + + padded = b"\x00" * crypto_box_ZEROBYTES + message + ciphertext = lib.ffi.new("unsigned char[]", len(padded)) + + if lib.crypto_box_afternm(ciphertext, padded, len(padded), nonce, k) != 0: + raise CryptoError("An error occurred trying to encrypt the message") + + return lib.ffi.buffer(ciphertext, len(padded))[crypto_box_BOXZEROBYTES:] + + +def crypto_box_open_afternm(k, ciphertext, nonce): + """ + Decrypts and returns the encrypted message ``ciphertext``, using the shared + key ``k`` and the nonce ``nonce``. + + :param k: bytes + :param ciphertext: bytes + :param nonce: bytes + :rtype: bytes + """ + if len(k) != crypto_box_BEFORENMBYTES: + raise ValueError("Invalid shared key") + + if len(nonce) != crypto_box_NONCEBYTES: + raise ValueError("Invalid nonce") + + padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext plaintext = lib.ffi.new("unsigned char[]", len(padded)) - if lib.crypto_box_open( - plaintext, ciphertext, len(ciphertext), nonce, pk, sk): + if lib.crypto_box_open_afternm( + plaintext, padded, len(padded), nonce, k) != 0: raise CryptoError("An error occurred trying to decrypt the message") - return lib.ffi.buffer(plaintext, len(padded))[zero_bytes:] + return lib.ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:] diff --git a/src/nacl/c/crypto_scalarmult.py b/src/nacl/c/crypto_scalarmult.py new file mode 100644 index 0000000000000000000000000000000000000000..910552ba4af784084f2b9a5be4f84a0b2ea00c62 --- /dev/null +++ b/src/nacl/c/crypto_scalarmult.py @@ -0,0 +1,38 @@ +# Copyright 2013 Donald Stufft and individual contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import absolute_import, division, print_function + +from nacl import _lib as lib +from nacl.exceptions import CryptoError + + +crypto_scalarmult_BYTES = lib.crypto_scalarmult_bytes() +crypto_scalarmult_SCALARBYTES = lib.crypto_scalarmult_scalarbytes() + + +def crypto_scalarmult_base(n): + """ + Computes and returns the scalar product of a standard group element and an + integer ``n``. + + :param n: bytes + :rtype: bytes + """ + q = lib.ffi.new("unsigned char[]", crypto_scalarmult_BYTES) + + if lib.crypto_scalarmult_base(q, n) != 0: + raise CryptoError( + "An error occurred while computing the scalar product") + + return lib.ffi.buffer(q, crypto_scalarmult_SCALARBYTES)[:] diff --git a/src/nacl/public.py b/src/nacl/public.py index 33d88d8e88f9515e20b7e1d695393e5f128140c5..eb083116abbd32de1fd3440e52dc0807bd90ca2a 100644 --- a/src/nacl/public.py +++ b/src/nacl/public.py @@ -14,10 +14,11 @@ from __future__ import absolute_import from __future__ import division -from . import encoding -from .c import _lib as nacl -from .exceptions import CryptoError -from .utils import EncryptedMessage, StringFixer, random +import nacl.c +import nacl.c.crypto_box + +from nacl import encoding +from nacl.utils import EncryptedMessage, StringFixer, random class PublicKey(encoding.Encodable, StringFixer, object): @@ -31,7 +32,7 @@ class PublicKey(encoding.Encodable, StringFixer, object): :cvar SIZE: The size that the public key is required to be """ - SIZE = nacl.lib.crypto_box_PUBLICKEYBYTES + SIZE = nacl.c.crypto_box_PUBLICKEYBYTES def __init__(self, public_key, encoder=encoding.RawEncoder): self._public_key = encoder.decode(public_key) @@ -59,7 +60,7 @@ class PrivateKey(encoding.Encodable, StringFixer, object): :cvar SIZE: The size that the private key is required to be """ - SIZE = nacl.lib.crypto_box_SECRETKEYBYTES + SIZE = nacl.c.crypto_box_SECRETKEYBYTES def __init__(self, private_key, encoder=encoding.RawEncoder): # Decode the secret_key @@ -70,15 +71,10 @@ class PrivateKey(encoding.Encodable, StringFixer, object): raise ValueError( "The secret key must be exactly %d bytes long" % self.SIZE) - pk = nacl.ffi.new("unsigned char[]", PublicKey.SIZE) - - if not nacl.lib.crypto_scalarmult_curve25519_base(pk, private_key): - raise CryptoError("Failed to generate a key pair") - - _pkey = nacl.ffi.buffer(pk, nacl.lib.crypto_box_PUBLICKEYBYTES)[:] + raw_public_key = nacl.c.crypto_scalarmult_base(private_key) self._private_key = private_key - self.public_key = PublicKey(_pkey) + self.public_key = PublicKey(raw_public_key) def __bytes__(self): return self._private_key @@ -113,21 +109,14 @@ class Box(encoding.Encodable, StringFixer, object): :cvar NONCE_SIZE: The size that the nonce is required to be. """ - NONCE_SIZE = nacl.lib.crypto_box_NONCEBYTES + NONCE_SIZE = nacl.c.crypto_box_NONCEBYTES def __init__(self, private_key, public_key): if private_key and public_key: - _shared_key_size = nacl.lib.crypto_box_BEFORENMBYTES - _shared_key = nacl.ffi.new("unsigned char[]", _shared_key_size) - - if not nacl.lib.crypto_box_beforenm( - _shared_key, - public_key.encode(encoder=encoding.RawEncoder), - private_key.encode(encoder=encoding.RawEncoder), - ): - raise CryptoError("Failed to derive shared key") - - self._shared_key = nacl.ffi.buffer(_shared_key, _shared_key_size)[:] + self._shared_key = nacl.c.crypto_box_beforenm( + private_key.encode(encoder=encoding.RawEncoder), + public_key.encode(encoder=encoding.RawEncoder), + ) else: self._shared_key = None @@ -162,20 +151,11 @@ class Box(encoding.Encodable, StringFixer, object): raise ValueError("The nonce must be exactly %s bytes long" % self.NONCE_SIZE) - padded = b"\x00" * nacl.lib.crypto_box_ZEROBYTES + plaintext - ciphertext = nacl.ffi.new("unsigned char[]", len(padded)) - - if not nacl.lib.crypto_box_afternm( - ciphertext, - padded, - len(padded), - nonce, - self._shared_key, - ): - raise CryptoError("Encryption failed") - - box_zeros = nacl.lib.crypto_box_BOXZEROBYTES - ciphertext = nacl.ffi.buffer(ciphertext, len(padded))[box_zeros:] + ciphertext = nacl.c.crypto_box_afternm( + self._shared_key, + plaintext, + nonce, + ) encoded_nonce = encoder.encode(nonce) encoded_ciphertext = encoder.encode(ciphertext) @@ -209,20 +189,10 @@ class Box(encoding.Encodable, StringFixer, object): raise ValueError("The nonce must be exactly %s bytes long" % self.NONCE_SIZE) - padded = b"\x00" * nacl.lib.crypto_box_BOXZEROBYTES + ciphertext - plaintext = nacl.ffi.new("unsigned char[]", len(padded)) - - if not nacl.lib.crypto_box_open_afternm( - plaintext, - padded, - len(padded), - nonce, - self._shared_key, - ): - raise CryptoError( - "Decryption failed. Ciphertext failed verification") - - box_zeros = nacl.lib.crypto_box_ZEROBYTES - plaintext = nacl.ffi.buffer(plaintext, len(padded))[box_zeros:] + plaintext = nacl.c.crypto_box_open_afternm( + self._shared_key, + ciphertext, + nonce, + ) return plaintext