Giter VIP home page Giter VIP logo

pynacl's People

Contributors

aaannndddyyy avatar alex avatar ayrx avatar davidfischer avatar dciabrin avatar dependabot[bot] avatar dmrobertson avatar dreamsorcerer avatar dreid avatar dstufft avatar felipedau avatar hakavlad avatar hugovk avatar hwoarang avatar jackwink avatar jdufresne avatar justquick avatar kitterma avatar lapin0t avatar leesmet avatar lmctv avatar lucas-c avatar lvh avatar mmerickel avatar nbraud avatar negativemjark avatar reaperhulk avatar sergeyklay avatar va1entin avatar warner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pynacl's Issues

handling signed messages?

Hi,

Thanks for the awesome library. This is not a bug report so much as an assistance request.

When I sign a message as per the doc, the "signed" result is a string, both:

isinstance(signed, str)

and

isinstance(signed, nacl.signing.SignedMessage)

return true.

However I can't seem to encode the signed message like I can with all of the other provided objects.

When I attempt:

In [1]: import nacl.utils

In [2]: import nacl.signing

In [3]: signing_key = nacl.signing.SigningKey.generate()

In [4]: signed = signing_key.sign(b"abc123")

In [5]: signed.encode(encoder = nacl.encoding.HexEncoder)

I get the following error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-c597ca2a169e> in <module>()
----> 1 signed.encode(encoder = nacl.encoding.HexEncoder)

TypeError: 'encoder' is an invalid keyword argument for this function

So I used base64.b64encode to encode the signed message for transport, however once decoded on the other side I no longer have access to the "signed.signature" and "signed.message" attributes.

In [11]: signed.message
Out[11]: 'abc123'

In [12]: encoded = base64.b64encode(signed)

In [13]: decoded = base64.b64decode(encoded)

In [14]: encoded.message
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-68a604c6014b> in <module>()
----> 1 encoded.message

AttributeError: 'str' object has no attribute 'message'

Do I have to parse the signed message myself?
Is there any way to cast the signed str back to nacl.signing.SignedMessage to programmatically retrieve signed.message?

Errors "verifying" sodium

I've got a big dump here. I may be interpreting this incorrectly, but it appears that there is a problem "verifying" sodium, at line 77 of nacl.py. At first the problem occurred on my primary machine, but I fired up a clean Xubuntu sandbox and got the same issues.

In both experiments I am also a common factor, which is where I suspect the real issue is, but just in case, I'll try to be as detailed as possible about replicating it so the report is helpful. I'm going to keep trying stuff and report back.

System Info

Python version: 2.7.3
GCC Version: 4.7.2
libsodium version: 0.3 (static and dynamic/shared)
OS: 64bit Xubuntu

Symptoms

Static build of libsodium

payton@sidony:~/Documents/pynacl-master$ python setup.py test
/usr/bin/ld: /usr/local/lib/libsodium.a(libsodium_la-base.o): relocation R_X86_64_PC32 against symbol `base' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
Traceback (most recent call last):
  File "setup.py", line 10, in <module>
    import nacl.nacl
  File "/home/payton/Documents/pynacl-master/nacl/nacl.py", line 77, in <module>
    lib = ffi.verify("#include <sodium.h>", libraries=["sodium"])
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/api.py", line 305, in verify
    lib = self.verifier.load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 68, in load_library
    self.compile_module()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 56, in compile_module
    self._compile_module()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 137, in _compile_module
    outputfilename = ffiplatform.compile(tmpdir, self.get_extension())
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/ffiplatform.py", line 25, in compile
    outputfilename = _build(tmpdir, ext)
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/ffiplatform.py", line 50, in _build
    raise VerificationError('%s: %s' % (e.__class__.__name__, e))
cffi.ffiplatform.VerificationError: LinkError: command 'gcc' failed with exit status 1

Shared build of libsodium

payton@sidony:~/Documents/pynacl-master$ python setup.py test
Traceback (most recent call last):
  File "setup.py", line 10, in <module>
    import nacl.nacl
  File "/home/payton/Documents/pynacl-master/nacl/nacl.py", line 77, in <module>
    lib = ffi.verify("#include <sodium.h>", libraries=["sodium"])
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/api.py", line 305, in verify
    lib = self.verifier.load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 69, in load_library
    return self._load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 149, in _load_library
    return self._vengine.load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/vengine_cpy.py", line 123, in load_library
    raise ffiplatform.VerificationError(error)
cffi.ffiplatform.VerificationError: importing '/home/payton/Documents/pynacl-master/nacl/__pycache__/_cffi__x89766aa6x20a28d1e.so': libsodium.so.0: cannot open shared object file: No such file or directory

Skipping tests

I can skip the tests and it will build without errors. However, they resurface in attempts to import things from nacl:

payton@sidony:~/Documents/pynacl-master$ python
Python 2.7.3 (default, Sep 26 2012, 21:51:14) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import nacl.utils
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "nacl/utils.py", line 4, in <module>
    from . import nacl
  File "nacl/nacl.py", line 77, in <module>
    lib = ffi.verify("#include <sodium.h>", libraries=["sodium"])
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/api.py", line 305, in verify
    lib = self.verifier.load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 69, in load_library
    return self._load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/verifier.py", line 149, in _load_library
    return self._vengine.load_library()
  File "/usr/local/lib/python2.7/dist-packages/cffi-0.5-py2.7-linux-x86_64.egg/cffi/vengine_cpy.py", line 123, in load_library
    raise ffiplatform.VerificationError(error)
cffi.ffiplatform.VerificationError: importing '/home/payton/Documents/pynacl-master/nacl/__pycache__/_cffi__x89766aa6x20a28d1e.so': libsodium.so.0: cannot open shared object file: No such file or directory

Sandbox Setup

sudo apt-get install build-essentials python-dev python-setuptools libffi-dev cython git
cd Documents

Here I downloaded a libsodium tarball (0.3) and built with

./configure && make && make check && sudo make install

then continued setting up...

git clone https://github.com/dstufft/pynacl.git
cd pynacl
python setup.py test

I verified that libsodium was correctly installed by building and running this program:

#include <stdio.h>
#include <sodium.h>

int main ()
{
    printf("Hello world!\n");
    return 0;
}

via

gcc hello.c -o hello -lsodium
./hello

To further verify it I built some other programs that used it extensively which would be too much to paste here, but I don't think that is where the problem is.

Public-Key Decryption fails if nonce is passed to decrypt()

The docstring suggests the nonce should be passed:

    def decrypt(self, ciphertext, nonce=None, encoder=encoding.RawEncoder):
        """
        Decrypts the ciphertext using the given nonce and returns the
        plaintext message.

        :param ciphertext: [:class:`bytes`] The encrypted message to decrypt
        :param nonce: [:class:`bytes`] The nonce used when encrypting the
            ciphertext
        <...>

On the other hand, the documentation example omits the nonce when calling decrypt(), which works as advertised.

I'm guessing nacl/sodium attach the nonce into the encrypted message? should probably modify decrypt()'s signature accordingly if that's the case.

Decrypting short data gives 'ValueError: The nonce must be exactly 24 bytes long'

Hi,
I'm giving box.decrypt() random data, and I expect that with high probability I will get CryptoError. (Because the ciphertext should contain an authenticator, and it should be hard to generate a valid ciphertext).

When using box.decrypt() for short random data, I get ValueError. (Which I think is a wrong behaviour). If I use it for longer random data, I get CryptoError (Which I consider to be the correct expected behaviour).

I include here my ipython transcript that shows how to reproduce this behaviour.
I'm using python 3.4 on Ubuntu 14.04 over PC, if it matters.

In [28]: import nacl.secret

In [29]: import nacl.utils

In [30]: key = nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)

In [31]: box = nacl.secret.SecretBox(key)

In [32]: message = b'This is the plaintext'

In [33]: nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)

In [34]: encrypted = box.encrypt(message,nonce)

In [35]: plaintext = box.decrypt(encrypted)

In [36]: plaintext
Out[36]: b'This is the plaintext'

In [37]: box.decrypt(b'Short')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-37-3326120b0dc5> in <module>()
----> 1 box.decrypt(b'Short')

/home/real/.virtualenvs/mep_backend/lib/python3.4/site-packages/nacl/secret.py in decrypt(self, ciphertext, nonce, encoder)
    113         if len(nonce) != self.NONCE_SIZE:
    114             raise ValueError(
--> 115                 "The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
    116             )
    117 

ValueError: The nonce must be exactly 24 bytes long

In [38]: box.decrypt(b'This is some longer data')
---------------------------------------------------------------------------
CryptoError                               Traceback (most recent call last)
<ipython-input-38-f837d208f3d7> in <module>()
----> 1 box.decrypt(b'This is some longer data')

/home/real/.virtualenvs/mep_backend/lib/python3.4/site-packages/nacl/secret.py in decrypt(self, ciphertext, nonce, encoder)
    117 
    118         plaintext = nacl.bindings.crypto_secretbox_open(ciphertext,
--> 119                                                         nonce, self._key)
    120 
    121         return plaintext

/home/real/.virtualenvs/mep_backend/lib/python3.4/site-packages/nacl/bindings/crypto_secretbox.py in crypto_secretbox_open(ciphertext, nonce, key)
     72     if lib.crypto_secretbox_open(
     73             plaintext, padded, len(padded), nonce, key) != 0:
---> 74         raise CryptoError("Decryption failed. Ciphertext failed verification")
     75 
     76     plaintext = lib.ffi.buffer(plaintext, len(padded))

CryptoError: Decryption failed. Ciphertext failed verification

Document Compiling On Windows

Okay, so here's how I have it building against Windows with the changes in #164:

  • Grab the latest libsodium-msvc release from downloads.libsodium.org
  • Unzip it and put it some place like C:\libsodium
  • Grab http://msinttypes.googlecode.com/svn/trunk/stdint.h and put that in C:\libsodium\include (this is required for Python 2.7 but not other releases)
  • The MSVC release zip from libsodium does not have a 64-bit VS2010 release, so to link against Python 64-bit 2.7 (which is technically built against VS2008 but links just fine against the VS2010 static libs) you need to check out the libsodium git source https://github.com/jedisct1/libsodium, check out the latest release tag, then open the vcxproj file for VS2010 (it's in builds/msvc/vs2010/libsodium), set the target to static release, then build it. You can then use the resulting .lib to statically link.

With those prerequisites out of the way you can then do something like this to build:

@set SODIUM_INSTALL=system
@set PYNACL_SODIUM_STATIC=1
@set LIB="C:\libsodium\path\to\static\lib\you\need";%LIB%
@set INCLUDE="C:\libsodium\include";%INCLUDE%
pip install .

(The PYNACL_SODIUM_STATIC flag is required if you want to link against the static libraries, but not if you want to use dynamic. If you use dynamic you'll need to drop the .lib file in the appropriate place post-install though and building a wheel will be a more involved process)

The next release of pynacl will ship static windows wheels by default so this is only necessary for users who don't want to wait or want to develop this project on windows.

Fix the order in which ffi.cdef() is called for the included header files

Currently PyNaCl obtains a list of header files using glob.glob(), then calls ffi.cdef() for each header file. This breaks horribly at runtime if the order of glob() is different from what it was at build time (which may happen with some file systems, or after restoring a backup), resulting in very cryptic errors at runtime, even though the build/install step succeeded just fine:

python -m nacl.public
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/uws/.virtualenvs/38aee272d0994fde/lib/python2.7/site-packages/PyNaCl-0.2.3-py2.7-linux-x86_64.egg/nacl/public.py", line 17, in <module>
    import nacl.c
  File "/home/uws/.virtualenvs/38aee272d0994fde/local/lib/python2.7/site-packages/PyNaCl-0.2.3-py2.7-linux-x86_64.egg/nacl/c/__init__.py", line 16, in <module>
    from nacl.c.crypto_box import (
  File "/home/uws/.virtualenvs/38aee272d0994fde/local/lib/python2.7/site-packages/PyNaCl-0.2.3-py2.7-linux-x86_64.egg/nacl/c/crypto_box.py", line 23, in <module>
    crypto_box_SECRETKEYBYTES = lib.crypto_box_secretkeybytes()
  File "/home/uws/.virtualenvs/38aee272d0994fde/local/lib/python2.7/site-packages/PyNaCl-0.2.3-py2.7-linux-x86_64.egg/nacl/_lib/__init__.py", line 76, in __getattr__
    self._lib = self.ffi.verifier.load_library()
  File "/home/uws/.virtualenvs/38aee272d0994fde/local/lib/python2.7/site-packages/cffi-0.7.2-py2.7-linux-x86_64.egg/cffi/verifier.py", line 68, in load_library
    self.compile_module()
  File "/home/uws/.virtualenvs/38aee272d0994fde/local/lib/python2.7/site-packages/PyNaCl-0.2.3-py2.7-linux-x86_64.egg/nacl/_lib/__init__.py", line 71, in _compile_module
    raise RuntimeError("Cannot compile module during runtime")
RuntimeError: Cannot compile module during runtime

Under the hood CFFI generates file names like _cffi__xd64d2119xefb54d7c.so at compile time, and tries to load a different file at runtime. The reason for this is that the CRC32 part of the file name is based on (among other things) a concatenation of the strings passed fo ffi.cdef(), in the order it was called.

The fix is to always .cdef() the headers in the same order.

pip-installable, without a system-installed libsodium

We were chatting about this on twitter a few days ago.. I've got an app for which I'd like to use nacl, and pynacl/libsodium looks like the best approach. But I'd like to make the build process for my app really easy (for developers). Which means I'd like them to be able to checkout my source code, run a few commands, and have a functioning program. I'm doing this by building a virtualenv and using pip install to populate it with my app's dependencies.

But pynacl needs libsodium installed in a place where CFFI can find it, and it seems like that means /usr/lib or /usr/local/lib (and include/), which is a drag: my prospective developers would have to start with unpacking the libsodium tarball and then a ./configure && make && sudo make install, scribbling over global directories in the process. After that, they could probably use pip to install the deps and get a working pynacl that references /usr/local/lib/libsodium.a .

One approach I've taken (with the other pynacl: https://github.com/warner/pynacl , in particular the "embed" branch) is to copy the nacl source code into the bindings project tree, then either hand-write the C-API glue code, or use SWIG. That's a drag, but it lets all the right compiler flags get used, and the result is a single .so file that doesn't reference anything else. And pip works (I think).

Doing that with this pynacl would mean running libsodium's ./configure, then copying all the .h and .c files into the tree, then writing glue code. Ick.

Another possibility is copying those files into the tree, then telling CFFI to include (concatenate?) all of them when building the .so, instead of using a libraries= argument to ffi.verify. I have no idea if that would work.

Another crazy idea is to first build and install libsodium into the nacl directory, using ./configure --prefix=./nacl && make && make install, so you wind up with nacl/nacl.py and nacl/lib/libsodium.so and nacl/include/sodium.h. Then you update setup.py to convince it to install those extra lib/include files as if they were source files. Then you modify nacl.py to look next to itself for the headers and libs. If you change setup.py's build target to run configure and make, I think the result would be pip-installable, at least on a system which has make and the right compilers.

Any other thoughts on how we might make it easier to use pynacl from other projects?

Rename `nacl.c` to something else to avoid silent security failures

In the upcoming v0.3.0 release, the ordering of arguments in the crypto_ API is being changed to match upstream. I suggest also renaming nacl.c itself in order to fail loudly for users of that API, rather than quietly changing behavior between releases.

Ideas for the new name:

  • nacl.real -- because it's the real nacl interface
  • nacl.crypto -- because all of the functions start with crypto_
  • nacl.std -- because it's the standard interface documented at http://nacl.cr.yp.to/

crypto_generichash

It would be useful to expose the crypto_generichash method (Blake2b).

Working on a project now that calls for Blake2b, but that doesn't seem to be exposed anywhere.

CFFI warning on startup

A script using PyNaCl prints the following warning:

/Library/Python/2.7/site-packages/cffi/vengine_cpy.py:166: UserWarning: reimporting '_cffi__xe8229e48xefb54d7c' might overwrite older definitions
% (self.verifier.get_module_name()))

This example is from Mac OS X, but it happened on OpenBSD as well. The culprit is the nacl module's init.py, which has a state variable that seems intended to track whether the module is initialized, but the variable is never modified. I'll create a pull request that fixes this.

`nacl.public.PrivateKey` class has no len() method

In [28]: box = nacl.secret.SecretBox(key)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-28-a37494c8a1fd> in <module>()
----> 1 box = nacl.secret.SecretBox(key)

/usr/local/lib/python2.7/dist-packages/PyNaCl-0.1.0-py2.7-linux-x86_64.egg/nacl/secret.pyc in __init__(self, key, encoder)
     47         key = encoder.decode(key)
     48
---> 49         if len(key) != self.KEY_SIZE:
     50             raise ValueError("The key must be exactly %s bytes long" %
     51                                 nacl.lib.crypto_secretbox_KEYBYTES)

TypeError: object of type 'PrivateKey' has no len()

Built from commit fa71dfbea5496a9be8477c8c133845ed3eb05656 on branch master.

Provide an example of handling large messages

It would be beneficial to have a clear example of handling messages not feasible to load to memory fully: the simplest use case would be encrypting/decrypting a file.

How could the secret key encryption example be adapted for file encryption?

Should a file or stream be read in chunks (obviously) and each of the chunk be encrypted with a separate box.encrypt call or there's a better way?

Support Sodium Optmizations

Sodium has recently added the ability to select optimized implementations of the various routines. In order to support this (and newer versions of Sodium) PyNaCl will need to call sodium_init prior to doing any work with Sodium, sodium_reinit anytime a fork happens, and sodium_shutdown before exiting the program.

progress indicator

Hello,

I'm wondering is there any way to get a progress indicator for the nacl.signing.SigningKey.generate()
function ?
I'm willing to do also a patch of libsodium if necessary to get a progress indication.

document/fix API differences

I prefer the "high-level" OOP-ish API, of course, but while comparing the low-level exposed libsodium functions (e.g. crypto_box()) against the upstream libraries and other language bindings, I noticed that the PyNaCl arguments appear in a different order:

  • nacl (C): crypto_box(&ciphertext, &msg, msglen, &nonce, &pubkey, &secretkey)
  • libsodium (C): crypto_box(&ciphertext, &msg, msglen, &nonce, &pubkey, &secretkey)
  • node-sodium (JS): ct = crypto_box(msg, nonce, pubkey, secretkey)
  • PyNaCl: ct = crypto_box(secretkey, pubkey, msg, nonce)

I don't know how they got flipped, but we should probably either flip them back (so anyone looking at the upstream NaCl or libsodium docs will correctly intuit how it's supposed to work), or document the heck out of them.

Triage issues for 0.5.0

As part of the 0.4.0 release process we should triage the issues we want to tackle for 0.5.0. This issue is just to remind us to do that before releasing 0.4.0.

Have classes `nacl.encoding` implement an ABC

It might be a good idea to define an ABC that all the classes in the nacl.encoding module implement. It will then be possible to do a isinstance check on all the places that takes a encoder as a parameter to make sure no one passes in anything stupid.

Thoughts?

add aes256gcm support

Hi, aes256 gcm is a popular mode of of operation for the symmetric key cryptographic block ciphers. It is a recommendation for Block Cipher Modes of Operation of NIST and offical standards. GCM mode has been used in many area, such as IEEE 802.1AE , ipsec, ssh, tls etc. A lot of applications plan to adopt gcm mode of operation. So support ase256 gcm will be very promising.

Do you have interest in support aes256 gcm? I have submitted a pull request for aes256 gcm support. Could you please give some suggestions or review it. Thanks...

use docstrings or separate .rst files for docs?

In #73 @lvh noticed that #77 removed a bunch of docstrings, in favor of separate .rst files. Are we cool with this? I agree with @lvh that docstrings are awfully handy. (I hadn't realized that removing the "autodoc" code was related to removing docstrings).

Personally, I'm -0 on removing docstrings. I like having API summaries in the docstrings, and then longer-form prose/tutorial/examples in the standalone files.

I'll volunteer to write docstrings if someone tells me what format I should use. Maybe they'd be easier to write/maintain if they don't need to be machine-readable?

nacl.c API swaps private & public keys + other things

The nacl.c Python module in PyNaCl 0.2.3 implements an API that appears to be the standard "NaCl" API, but actually permutes its arguments and return values in a way that is both surprising and confusing to developers who are familiar with the NaCl C and C++ APIs.

A useful thing about NaCl, as proposed by D.J.Bernstein et al., is that it provides a notation for certain cryptographic operations that is easy to understand both for programmers and academics. One can read c = crypto_box(m, n, pk, sk) in an academic paper or a protocol design document, understand what it means, and simply transcribe it into code. This is a great way to avoid costly transcription errors such as the ECDSA nonce reuse bug that affected PlayStation 3.

So, going from the standard NaCl documentation, the following code should work:

from nacl.c import *
k = randombytes(crypto_secretbox_KEYBYTES)
n = randombytes(crypto_secretbox_NONCEBYTES)
m = b'TheQuickBrownFoxJumps...'
c = crypto_secretbox(m,n,k)

Surprisingly, it fails:

Traceback (most recent call last):                                                                 
  File "<stdin>", line 1, in <module>
  File "[...]/python3.4/site-packages/nacl/c/crypto_secretbox.py", line 37, in crypto_secretbox
    raise ValueError("Invalid key")
ValueError: Invalid key

Worse, the following code raises no exception, and quietly assigns the public key to sk and the private key to pk:

 pk, sk = crypto_box_keypair()

This is a security disaster waiting to happen. PyNaCl calls itself "NaCl" and provides exactly the same function names as NaCl does, but those functions do not behave the same as they do in NaCl.

Here's a table showing the dfferences between the crypto_* API as documented by NaCl and as implemented in PyNaCl (I've Pythonified the NaCl API as indicated to ease the comparison, but I think you'll agree that it follows logically from the NaCl documentation):

nacl.cr.yp.to documentation pynacl implementation
pk, sk = crypto_box_keypair(); /* inferred */ sk, pk = crypto_box_keypair()
c = crypto_box(m,n,pk,sk); c = crypto_box(sk,pk,m,n)
m = crypto_box_open(c,n,pk,sk); m = crypto_box_open(sk,pk,c,n)
k = crypto_box_beforenm(pk,sk); /* inferred */ k = crypto_box_beforenm(sk,pk)
c = crypto_box_afternm(m,n,k); /* inferred */ c = crypto_box_afternm(k,m,n)
m = crypto_box_open_afternm(c,n,k); /* inferred */ m = crypto_box_open_afternm(k,c,n)
q = crypto_scalarmult(n,p); ## not implemented ##
q = crypto_scalarmult_base(n); q = crypto_scalarmult_base(n)
pk, sk = crypto_sign_keypair(); /* inferred */ sk, pk = crypto_sign_keypair()
sm = crypto_sign(m,sk); sm = crypto_sign(sk,m)
m = crypto_sign_open(sm,pk); m = crypto_sign_open(pk,sm)
/* not documented */ sk, pk = crypto_sign_seed_keypair(seed)
c = crypto_secretbox(m,n,k); c = crypto_secretbox(k,m,n)
m = crypto_secretbox_open(c,n,k); m = crypto_secretbox_open(k,c,n)
c = crypto_stream(clen,n,k); ## not implemented ##
c = crypto_stream_xor(m,n,k); ## not implemented ##
a = crypto_auth(m,k); ## not implemented ##
crypto_auth_verify(a,m,k); ## not implemented ##
a = crypto_onetimeauth(m,k); ## not implemented ##
crypto_onetimeauth_verify(a,m,k); ## not implemented ##
h = crypto_hash(m); h = crypto_hash(m)
h = crypto_hash_sha256(m); h = crypto_hash_sha256(m)
h = crypto_hash_sha512(m); h = crypto_hash_sha512(m)
/* not documented */ x = randombytes(size)
crypto_verify_16(x,y); ## not implemented ##
crypto_verify_32(x,y); ## not implemented ##

Of note:

  • In NaCl public-key operations, the public key always comes before the private key. In PyNaCl, the opposite is true.
  • In NaCl encryption/decryption operations, the argument ordering is "message before nonce before keys". In PyNaCl, it's "keys before message before nonce".

At this point, the nacl.c module should be removed and replaced with a differently-named module that implements the real NaCl interface.

Random Nonces by Default?

There are a number of places where the api expects a nonce. Ideally a nonce should never be reused. However DJB has stated for both Symmetrical and Asymmetrical encryption that with a random nonce the collision risk is negligible[1][2].

Currently PyNaCl documentation has lots of warnings but given with the "Crypto without the sharp edges" ideal should PyNaCl by default generate a random nonce? This will need a resolution to https://github.com/dstufft/pynacl/issues/20 or will need to change the encrypt() function to return a tuple of (nonce, ciphertext).

[1] http://nacl.cr.yp.to/box.html
[2] http://nacl.cr.yp.to/secretbox.html

Rename From PyNaCl to Sodium?

We don't actually wrap NaCl anymore and instead we depend on libsodium. Sodium started out as just a portable NaCl but it now includes things that NaCl doesn't. Additionally the NaCl name is easy to confuse with google's Native Client.

CFFI Warning on startup

This looks similar to #62 but is occurring in a build I made today which presumably has the fix in it. Indeed, the package contains _cffi_fix, so is there perhaps a leftover issue remaining?

Note the reimport is coming from my local build directory which is somehow still being linked to by the site-package version:

brandon@ubuntu:~/sites/griffin/clients/python/nacl$ python client.py 
/usr/local/src/pynacl-0.2.3/.eggs/cffi-0.8.6-py2.7-linux-x86_64.egg/cffi/vengine_cpy.py:177: UserWarning: reimporting '_cffi__x6bd3e85dx794f2fab' might overwrite older definitions
  % (self.verifier.get_module_name()))

Add __eq__() magic method to key classes

I'm using public keys as identifiers and need a way to check two such identifiers for equality. Now, the way the keys are stored internally by PyNaCl varies among the different key classes (nacl.public.PublicKey, nacl.public.VerifyKey, nacl.public.SigningKey, …) and I really don't want to rely on that. Hence, a magic method __eq__() would be a great thing to have.

I will probably add it myself in the coming days and create a pull request. Just wanted to write it down in the meantime.

Freezing an app using pynacl

Hello,

I'm tring to freeze my app. It's using pynacl.

I added "nacl" as a package, but when I try to launch it, it asks cffi to build the code and I get :
distutils.errors.DistutilsPlatformError: invalid Python installation: unable to open /include/python3.4m/pyconfig.h (No such file or directory)

Is it possible to prebuilt nacl so that it an be included in the freeze package ?

error: sodium.h: No such file or directory

PyNaCl installs fine using pip, but when imported it bugs out saying it can't find a file called sodium.h.

From my understanding, PyNaCl includes libsodium and doesn't need it to be pre-installed on the system. I also tried pre-installing it just to make sure, and got the same error. I also verified that sodium.h was found in my LD_LIBRARY_PATH, but no matter what I do I seem to get the same error.

Has anybody ever seen this before?

If you would like to reproduce it the exact environment (Heroku) you can do so by running:

git init
echo "PyNaCl" > requirements.txt
echo "cffi" >> requirements.txt
heroku create --buildpack git://github.com/kennethjiang/heroku-buildpack-python-libffi.git
git add .
git commit -m "test"
git push heroku master
heroku run 'python -c "import nacl.hash"'

The full content of the error I get is as follows:

~ $ python -c "import nacl.hash"
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:185:20: error: sodium.h: No such file or directory
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:269: warning: implicit declaration of function ‘crypto_box’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_afternm’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:345: warning: implicit declaration of function ‘crypto_box_afternm’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_beforenm’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:402: warning: implicit declaration of function ‘crypto_box_beforenm’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_beforenmbytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:416: warning: implicit declaration of function ‘crypto_box_beforenmbytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_boxzerobytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:430: warning: implicit declaration of function ‘crypto_box_boxzerobytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_keypair’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:474: warning: implicit declaration of function ‘crypto_box_keypair’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_noncebytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:488: warning: implicit declaration of function ‘crypto_box_noncebytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_open’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:577: warning: implicit declaration of function ‘crypto_box_open’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_open_afternm’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:653: warning: implicit declaration of function ‘crypto_box_open_afternm’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_publickeybytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:667: warning: implicit declaration of function ‘crypto_box_publickeybytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_secretkeybytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:681: warning: implicit declaration of function ‘crypto_box_secretkeybytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_box_zerobytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:695: warning: implicit declaration of function ‘crypto_box_zerobytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_hash’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:745: warning: implicit declaration of function ‘crypto_hash’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_hash_sha256’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:795: warning: implicit declaration of function ‘crypto_hash_sha256’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_hash_sha256_bytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:809: warning: implicit declaration of function ‘crypto_hash_sha256_bytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_hash_sha512’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:859: warning: implicit declaration of function ‘crypto_hash_sha512’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_hash_sha512_bytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:873: warning: implicit declaration of function ‘crypto_hash_sha512_bytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_scalarmult_base’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:917: warning: implicit declaration of function ‘crypto_scalarmult_base’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_scalarmult_bytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:931: warning: implicit declaration of function ‘crypto_scalarmult_bytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_scalarmult_scalarbytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:945: warning: implicit declaration of function ‘crypto_scalarmult_scalarbytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_secretbox’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1021: warning: implicit declaration of function ‘crypto_secretbox’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_secretbox_boxzerobytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1035: warning: implicit declaration of function ‘crypto_secretbox_boxzerobytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_secretbox_keybytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1049: warning: implicit declaration of function ‘crypto_secretbox_keybytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_secretbox_noncebytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1063: warning: implicit declaration of function ‘crypto_secretbox_noncebytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_secretbox_open’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1139: warning: implicit declaration of function ‘crypto_secretbox_open’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_secretbox_zerobytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1153: warning: implicit declaration of function ‘crypto_secretbox_zerobytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1229: warning: implicit declaration of function ‘crypto_sign’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign_bytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1243: warning: implicit declaration of function ‘crypto_sign_bytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign_keypair’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1287: warning: implicit declaration of function ‘crypto_sign_keypair’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign_open’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1363: warning: implicit declaration of function ‘crypto_sign_open’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign_publickeybytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1377: warning: implicit declaration of function ‘crypto_sign_publickeybytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign_secretkeybytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1391: warning: implicit declaration of function ‘crypto_sign_secretkeybytes’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_crypto_sign_seed_keypair’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1448: warning: implicit declaration of function ‘crypto_sign_seed_keypair’
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c: In function ‘_cffi_f_randombytes’:
.heroku/python/lib/python2.7/site-packages/nacl/_lib/__pycache__/_cffi__xac3ef8b2x44e2af4a.c:1484: warning: implicit declaration of function ‘randombytes’
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/app/.heroku/python/lib/python2.7/site-packages/nacl/hash.py", line 17, in <module>
    import nacl.c
  File "/app/.heroku/python/lib/python2.7/site-packages/nacl/c/__init__.py", line 16, in <module>
    from nacl.c.crypto_box import (
  File "/app/.heroku/python/lib/python2.7/site-packages/nacl/c/crypto_box.py", line 23, in <module>
    crypto_box_SECRETKEYBYTES = lib.crypto_box_secretkeybytes()
  File "/app/.heroku/python/lib/python2.7/site-packages/nacl/_lib/__init__.py", line 73, in __getattr__
    self._lib = self.ffi.verifier.load_library()
  File "/app/.heroku/python/lib/python2.7/site-packages/cffi/verifier.py", line 74, in load_library
    self._compile_module()
  File "/app/.heroku/python/lib/python2.7/site-packages/cffi/verifier.py", line 139, in _compile_module
    outputfilename = ffiplatform.compile(tmpdir, self.get_extension())
  File "/app/.heroku/python/lib/python2.7/site-packages/cffi/ffiplatform.py", line 25, in compile
    outputfilename = _build(tmpdir, ext)
  File "/app/.heroku/python/lib/python2.7/site-packages/cffi/ffiplatform.py", line 51, in _build
    raise VerificationError('%s: %s' % (e.__class__.__name__, e))
cffi.ffiplatform.VerificationError: CompileError: command 'gcc' failed with exit status 1
~ $

Thanks!

Add getter for ECDH key exchange's shared secret.

So as directed by your developer, /u/kingkilr, I'm asking you to add a way for users to access the parameters of DH key exchange.

There might be other use cases too, but at least in the one I'm working on where all key-exchange related data received needs to be manually typed on another computer, accessing the DH shared secret, (or the public encryption box's key derived from shared secret) would make it much easier (and more secure) for the users when they don't also have to write additional nonce, ciphertext and tag.

The reason I can't continuously use public key crypto box is lack of forward secrecy. So I want to use PyNaCl secret key crypto after key exchange, and refresh the shared secret key using HKDF similar to Silent Circle's SCIMP between messages.

Markus

'Read the docs' doesn't explain how to import public keys.

The documentation generates both key pair objects in the same program.

skbob = PrivateKey.generate()
pkbob = skbob.public_key
skalice = PrivateKey.generate()
pkalice = skalice.public_key

Once public key has been generated, the documentation says

# the public key can be given to anyone wishing to send Bob an encrypted message

There is however no documentation about how to I could import public key of Alice into Bob's client. I succeeded in this by doing

bobPrivateKey = PrivateKey.generate()
bobPublicKey = bobPrivateKey.public_key

alicePrivateKey = PrivateKey.generate()
alicePublicKey = alicePrivateKey.public_key
alicePublicKey.__init__(getPublicKey())

box = Box(bobPrivateKey, alicePublicKey)

but I'm not sure whether creating the temporary object is the correct way. Could you advice on how public key is supposed to be imported?

Thank You.

Linking with gold causes a build failure

Steps to reproduce: build with env CFLAGS="-fuse-ld=gold -flto" or similar.
Result:

[127.0.0.1] out:     make[2]: Entering directory `/tmp/pip-build-2VDruN/pynacl/build/temp.linux-x86_64-2.7/test/default'
[127.0.0.1] out:     make  aead_aes256gcm aead_chacha20poly1305 auth auth2 auth3 auth5 auth6 auth7 box box2 box7 box8 box_easy box_easy2 box_seal box_seed chacha20 core1 core2 core3 core4 core5 core6 ed25519_convert generichash generichas
h2 generichash3 hash hash3 onetimeauth onetimeauth2 onetimeauth7 pwhash pwhash_scrypt_ll randombytes scalarmult scalarmult2 scalarmult5 scalarmult6 scalarmult7 secretbox secretbox2 secretbox7 secretbox8 secretbox_easy secretbox_easy2 shor
thash sign sodium_core sodium_utils sodium_version stream stream2 stream3 stream4 verify1 sodium_utils2 sodium_utils3
[127.0.0.1] out:     make[3]: Entering directory `/tmp/pip-build-2VDruN/pynacl/build/temp.linux-x86_64-2.7/test/default'
[127.0.0.1] out:       CC       aead_aes256gcm.o
[127.0.0.1] out:       CCLD     aead_aes256gcm
[127.0.0.1] out:     /usr/lib/gcc/x86_64-linux-gnu/4.8/include/tmmintrin.h: In function 'blake2b_compress_sse41':
[127.0.0.1] out:     /usr/lib/gcc/x86_64-linux-gnu/4.8/include/tmmintrin.h:136:45: error: '__builtin_ia32_pshufb128' needs isa option -m32 -mssse3
[127.0.0.1] out:        return (__m128i) __builtin_ia32_pshufb128 ((__v16qi)__X, (__v16qi)__Y);
[127.0.0.1] out:                                                  ^
[127.0.0.1] out:     /usr/lib/gcc/x86_64-linux-gnu/4.8/include/tmmintrin.h:136:45: error: '__builtin_ia32_pshufb128' needs isa option -m32 -mssse3
[127.0.0.1] out:        return (__m128i) __builtin_ia32_pshufb128 ((__v16qi)__X, (__v16qi)__Y);
[127.0.0.1] out:                                                  ^
[127.0.0.1] out:     /usr/lib/gcc/x86_64-linux-gnu/4.8/include/tmmintrin.h:136:45: error: '__builtin_ia32_pshufb128' needs isa option -m32 -mssse3
[127.0.0.1] out:        return (__m128i) __builtin_ia32_pshufb128 ((__v16qi)__X, (__v16qi)__Y);
[127.0.0.1] out:                                                  ^
[127.0.0.1] out:     /usr/lib/gcc/x86_64-linux-gnu/4.8/include/tmmintrin.h:136:45: error: '__builtin_ia32_pshufb128' needs isa option -m32 -mssse3
[127.0.0.1] out:        return (__m128i) __builtin_ia32_pshufb128 ((__v16qi)__X, (__v16qi)__Y);


... continues for a bit ...

[127.0.0.1] out:     /usr/lib/gcc/x86_64-linux-gnu/4.8/include/tmmintrin.h:185:3: error: '__builtin_ia32_palignr128' needs isa option -m32 -mssse3
[127.0.0.1] out:        return (__m128i) __builtin_ia32_palignr128 ((__v2di)__X,
[127.0.0.1] out:        ^
[127.0.0.1] out:     lto-wrapper: gcc returned 1 exit status
[127.0.0.1] out:     /usr/bin/ld.gold: fatal error: lto-wrapper failed
[127.0.0.1] out:     collect2: error: ld returned 1 exit status
[127.0.0.1] out:     make[3]: *** [aead_aes256gcm] Error 1

IOError when importing nacl.public

Ran into this problem when importing nacl.public, after installing through PyPI. I think I've solved it now, but posting for comments and future reference. System: OSX 10.8.3.

import nacl.public
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PyNaCl-0.1.0-py2.7-macosx-10.8-x86_64.egg/nacl/public.py", line 6, in
from . import nacl, encoding
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PyNaCl-0.1.0-py2.7-macosx-10.8-x86_64.egg/nacl/nacl.py", line 77, in
lib = ffi.verify("#include <sodium.h>", libraries=["sodium"])
File "/Users/mark/org/src/cffi/cffi/api.py", line 311, in verify
lib = self.verifier.load_library()
File "/Users/mark/org/src/cffi/cffi/verifier.py", line 68, in load_library
self.compile_module()
File "/Users/mark/org/src/cffi/cffi/verifier.py", line 55, in compile_module
self._write_source()
File "/Users/mark/org/src/cffi/cffi/verifier.py", line 117, in _write_source
file = open(self.sourcefilename, 'w')
IOError: [Errno 2] No such file or directory: '/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PyNaCl-0.1.0-py2.7-macosx-10.8-x86_64.egg/nacl/pycache/_cffi__xc7279a62x20a28d1e.c'

The problem persisted when installed directly from sources, however, when running the python process as root there was no error. Also, when installing with sudo python setup.py develop, running python as the user owning the source folder didn't cause any error.

After debugging the issue and searching online, I found a section in the cffi docs, with which I managed to solve the issue, by adding

ffi.verify("...", ext_package='nacl')

to the setup.py file.

should PrivateKey.__init__() do Curve25519 key masking?

Curve25519 requires some bits in the secret key to bet set/cleared, and NaCl/libsodium do that clearing automatically when they do curve multiplication. That means that some bits in the input are ignored, and it's possible to have different-looking keys that are functionally the same.

PyNaCl's PrivateKey.encode() method isn't aware of this detail; the input bytes are returned exactly as they were given to __init__(). So it's possible to have two PrivateKey objects that look different but result in the same public key. Here's an example.

Should __init__() mask the private key before storing it? It's hard for me to imagine this really mattering in practice, but it might be slightly more correct.

expose BLAKE2

Dear pynacl developers:

Thank you very much for this library!

I request that pynacl expose the "generic hash" function from
libsodium (https://download.libsodium.org/doc/hashing/generic_hashing.html).
This is, of course, BLAKE2!

Reasons:

  • It's safer than SHA-256 or SHA-512, because it is invulnerable to
    length-extension.
  • It is descended from and closely related to BLAKE, which got higher
    marks than even Keccak got in the SHA-3 contest (please see
    https://blake2.net/acns/slides.html ).
  • It is descended from and closely related to Salsa20 and ChaCha20,
    which have gotten much scrutiny and passed with flying colors.
  • It is much more efficient than SHA-256 or SHA-512 for most platforms and uses.
  • It is what the authors of libsodium thought should be the default
    hash function for users who didn't have a reason to choose a different
    hash function.
  • An implementation of it is already shipping inside pynacl, and has
    been all along, it just isn't exposed in the API.
  • It's what the hip modern applied cryptographer reaches for when they
    need a secure hash function (e.g. the Password Hashing Competition
    entrants on https://blake2.net/#us).
  • It is currently being added to Bouncy Castle, Crypto++, and OpenSSL.
    You don't want to be the last kid on your block to support BLAKE2 do
    you !?
  • https://github.com/saltstack/libnacl and https://pypi.python.org/pypi/pysodium already expose BLAKE2 a.k.a. "generic hash".

Update libsodium to 0.5+

Changelog:

  • Version 0.5.0
    • sodium_mlock()/sodium_munlock() have been introduced to lock pages
      in memory before storing sensitive data, and to zero them before
      unlocking them.
    • High-level wrappers for crypto_box and crypto_secretbox
      (crypto_box_easy and crypto_secretbox_easy) can be used to avoid
      dealing with the specific memory layout regular functions depend on.
    • crypto_pwhash_scryptsalsa208sha256* functions have been added
      to derive a key from a password, and for password storage.
    • Salsa20 and ed25519 implementations now support overlapping
      inputs/keys/outputs (changes imported from supercop-20140505).
    • New build scripts for Visual Studio, Emscripten, different Android
      architectures and msys2 are available.
    • The poly1305-53 implementation has been replaced with Floodyberry's
      poly1305-donna32 and poly1305-donna64 implementations.
    • sodium_hex2bin() has been added to complement sodium_bin2hex().
    • On OpenBSD and Bitrig, arc4random() is used instead of reading
      /dev/urandom.
    • crypto_auth_hmac_sha512() has been implemented.
    • sha256 and sha512 now have a streaming interface.
    • hmacsha256, hmacsha512 and hmacsha512256 now support keys of
      arbitrary length, and have a streaming interface.
    • crypto_verify_64() has been implemented.
    • first-class Visual Studio build system, thanks to @evoskuil
    • CPU features are now detected at runtime.

missing crypto_scalarmult() function

It looks like src/nacl/c/crypto_scalarmult.c offers the crypto_scalarmult_base() function (which takes a buffer-encoded integer and multiplies it by the standard base point), but doesn't expose the more general crypto_scalarmult() function (which takes an integer and a point, and returns a new point). The latter is necessary to do low-level DH agreement, like for the Axolotl triple-DH ratchet, when it's not embedded inside a high-level crypto_box() function.

I'll work on a patch.

Incidentally, the names exposed in src/nacl/c/__init__.py are a bit weird: it imports names from submodules that shadow the submodule itself. Like crypto_secretbox here:

from nacl.c.crypto_secretbox import (
    crypto_secretbox_KEYBYTES, crypto_secretbox_NONCEBYTES,
    crypto_secretbox_ZEROBYTES, crypto_secretbox_BOXZEROBYTES,
    crypto_secretbox, crypto_secretbox_open,
)

When I add crypto_scalarmult() to src/nacl/c/crypto_scalarmult.py, we'll have another instance of this.

If the intention is that import nacl.c should be enough to access everything exported by all modules in src/nacl/c/*.py, I'm cool with that, although maybe the imports in __init__.py should be relative? (from .crypto_secretbox import ...?)

release v0.3.0

I'd like to see a new release soon. I'm thinking we should block on #72, #52, and the docs overhaul (removing autodocs) that @Ayrx is working on to let the #52 branch pass. How's that sound?

"python setup.py install" breaks the sources

So it can't be reran, resulting in an error:

running install
running build
running build_py
running build_clib
error: [Errno 17] File exists: '/tmp/pynacl/build/temp.linux-x86_64-2.7'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.