summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah Anderson <micah@riseup.net>2013-11-14 16:35:32 -0500
committerMicah Anderson <micah@riseup.net>2013-11-14 16:35:32 -0500
commitc8b79bf686113c3418d8d65ff0a1920da2b409bc (patch)
tree4c76ad4dcedcbd25d653d261ad5033bf21911f0f
initial commit
-rw-r--r--PKG-INFO139
-rw-r--r--README.rst121
-rw-r--r--debian/changelog29
-rw-r--r--debian/compat1
-rw-r--r--debian/control20
-rw-r--r--debian/copyright43
-rw-r--r--debian/python-scrypt.lintian-overrides4
-rwxr-xr-xdebian/rules6
-rw-r--r--debian/source/format1
-rw-r--r--scrypt-1.1.6/config.h99
-rw-r--r--scrypt-1.1.6/lib/crypto/crypto_aesctr.c124
-rw-r--r--scrypt-1.1.6/lib/crypto/crypto_aesctr.h59
-rw-r--r--scrypt-1.1.6/lib/crypto/crypto_scrypt-nosse.c345
-rw-r--r--scrypt-1.1.6/lib/crypto/crypto_scrypt.h46
-rw-r--r--scrypt-1.1.6/lib/crypto/sha256.c412
-rw-r--r--scrypt-1.1.6/lib/crypto/sha256.h62
-rw-r--r--scrypt-1.1.6/lib/scryptenc/scryptenc.c633
-rw-r--r--scrypt-1.1.6/lib/scryptenc/scryptenc.h112
-rw-r--r--scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.c192
-rw-r--r--scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.h39
-rw-r--r--scrypt-1.1.6/lib/util/memlimit.c343
-rw-r--r--scrypt-1.1.6/lib/util/memlimit.h42
-rw-r--r--scrypt-1.1.6/lib/util/readpass.h45
-rw-r--r--scrypt-1.1.6/lib/util/sysendian.h140
-rw-r--r--scrypt-1.1.6/lib/util/warn.c75
-rw-r--r--scrypt-1.1.6/lib/util/warn.h13
-rw-r--r--scrypt-1.1.6/scrypt_platform.h12
-rw-r--r--scrypt.py224
-rw-r--r--setup.py105
-rw-r--r--src/scrypt.c74
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/ciphertexts.csv6
-rw-r--r--tests/hashvectors.csv5
-rw-r--r--tests/test_scrypt.py285
-rw-r--r--tests/test_scrypt_py2x.py51
-rw-r--r--tests/test_scrypt_py3x.py56
36 files changed, 3963 insertions, 0 deletions
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..6d65038
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,139 @@
+Metadata-Version: 1.0
+Name: scrypt
+Version: 0.6.1
+Summary: Bindings for the scrypt key derivation function library
+Home-page: http://bitbucket.org/mhallin/py-scrypt
+Author: Magnus Hallin
+Author-email: mhallin@gmail.com
+License: 2-clause BSD
+Description: =========================
+ Python scrypt_ bindings
+ =========================
+
+ This is a set of Python_ bindings for the scrypt_ key derivation
+ function.
+
+ Scrypt is useful when encrypting password as it is possible to specify
+ a *minimum* amount of time to use when encrypting and decrypting. If,
+ for example, a password takes 0.05 seconds to verify, a user won't
+ notice the slight delay when signing in, but doing a brute force
+ search of several billion passwords will take a considerable amount of
+ time. This is in contrast to more traditional hash functions such as
+ MD5 or the SHA family which can be implemented extremely fast on cheap
+ hardware.
+
+ Installation
+ ============
+
+ You can install py-scrypt from this repository if you want the latest
+ but possibly non-compiling version::
+
+ $ hg clone http://bitbucket.org/mhallin/py-scrypt
+ $ cd py-scrypt
+ $ python setup.py build
+
+ Become superuser (or use virtualenv):
+ # python setup.py install
+
+ Run tests after install:
+ $ python setup.py test
+
+ Or you can install the latest release from PyPi::
+
+ $ pip install scrypt
+
+ If you want py-scrypt for your Python 3 environment, just run the
+ above commands with your Python 3 interpreter. Py-scrypt supports both
+ Python 2 and 3.
+
+ From version 0.6.0 (not available on PyPi yet), py-scrypt supports
+ PyPy as well.
+
+ Usage
+ =====
+
+ Fore encryption/decryption, the library exports two functions
+ ``encrypt`` and ``decrypt``::
+
+ >>> import scrypt
+ >>> data = scrypt.encrypt('a secret message', 'password', maxtime=0.1) # This will take at least 0.1 seconds
+ >>> data[:20]
+ 'scrypt\x00\r\x00\x00\x00\x08\x00\x00\x00\x01RX9H'
+ >>> scrypt.decrypt(data, 'password', maxtime=0.1) # This will also take at least 0.1 seconds
+ 'a secret message'
+ >>> scrypt.decrypt(data, 'password', maxtime=0.05) # scrypt won't be able to decrypt this data fast enough
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ scrypt.error: decrypting file would take too long
+ >>> scrypt.decrypt(data, 'wrong password', maxtime=0.1) # scrypt will throw an exception if the password is incorrect
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ scrypt.error: password is incorrect
+
+ From these, one can make a simple password verifier using the following
+ functions::
+
+ def randstr(length):
+ return ''.join(chr(random.randint(0,255)) for i in range(length))
+
+ def hash_password(password, maxtime=0.5, datalength=64):
+ return scrypt.encrypt(randstr(datalength), password, maxtime=maxtime)
+
+ def verify_password(hashed_password, guessed_password, maxtime=0.5):
+ try:
+ scrypt.decrypt(hashed_password, guessed_password, maxtime)
+ return True
+ except scrypt.error:
+ return False
+
+
+ But, if you want output that is deterministic and constant in size,
+ you can use the ``hash`` function::
+
+ >>> import scrypt
+ >>> h1 = scrypt.hash('password', 'random salt')
+ >>> len(h1) # The hash will be 64 bytes by default, but is overridable.
+ 64
+ >>> h1[:10]
+ '\xfe\x87\xf3hS\tUo\xcd\xc8'
+ >>> h2 = scrypt.hash('password', 'random salt')
+ >>> h1 == h2 # The hash function is deterministic
+ True
+
+
+ Acknowledgements
+ ================
+
+ Scrypt_ was created by Colin Percival and is licensed as 2-clause BSD.
+ Since scrypt does not normally build as a shared library, I have included
+ the source for the currently latest version of the library in this
+ repository. When a new version arrives, I will update these sources.
+
+ `Kelvin Wong`_ on Bitbucket provided changes to make the library
+ available on Mac OS X 10.6 and earlier, as well as changes to make the
+ library work more like the command-line version of scrypt by
+ default. Kelvin also contributed with the unit tests, lots of cross
+ platform testing and work on the ``hash`` function.
+
+ Burstaholic_ on Bitbucket provided the necessary changes to make
+ the library build on Windows.
+
+ License
+ =======
+
+ This library is licensed under the same license as scrypt; 2-clause BSD.
+
+ .. _scrypt: http://www.tarsnap.com/scrypt.html
+ .. _Python: http://python.org
+ .. _Burstaholic: https://bitbucket.org/Burstaholic
+ .. _Kelvin Wong: https://bitbucket.org/kelvinwong_ca
+
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Security :: Cryptography
+Classifier: Topic :: Software Development :: Libraries
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..f567b6c
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,121 @@
+=========================
+ Python scrypt_ bindings
+=========================
+
+This is a set of Python_ bindings for the scrypt_ key derivation
+function.
+
+Scrypt is useful when encrypting password as it is possible to specify
+a *minimum* amount of time to use when encrypting and decrypting. If,
+for example, a password takes 0.05 seconds to verify, a user won't
+notice the slight delay when signing in, but doing a brute force
+search of several billion passwords will take a considerable amount of
+time. This is in contrast to more traditional hash functions such as
+MD5 or the SHA family which can be implemented extremely fast on cheap
+hardware.
+
+Installation
+============
+
+You can install py-scrypt from this repository if you want the latest
+but possibly non-compiling version::
+
+ $ hg clone http://bitbucket.org/mhallin/py-scrypt
+ $ cd py-scrypt
+ $ python setup.py build
+
+ Become superuser (or use virtualenv):
+ # python setup.py install
+
+ Run tests after install:
+ $ python setup.py test
+
+Or you can install the latest release from PyPi::
+
+ $ pip install scrypt
+
+If you want py-scrypt for your Python 3 environment, just run the
+above commands with your Python 3 interpreter. Py-scrypt supports both
+Python 2 and 3.
+
+From version 0.6.0 (not available on PyPi yet), py-scrypt supports
+PyPy as well.
+
+Usage
+=====
+
+Fore encryption/decryption, the library exports two functions
+``encrypt`` and ``decrypt``::
+
+ >>> import scrypt
+ >>> data = scrypt.encrypt('a secret message', 'password', maxtime=0.1) # This will take at least 0.1 seconds
+ >>> data[:20]
+ 'scrypt\x00\r\x00\x00\x00\x08\x00\x00\x00\x01RX9H'
+ >>> scrypt.decrypt(data, 'password', maxtime=0.1) # This will also take at least 0.1 seconds
+ 'a secret message'
+ >>> scrypt.decrypt(data, 'password', maxtime=0.05) # scrypt won't be able to decrypt this data fast enough
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ scrypt.error: decrypting file would take too long
+ >>> scrypt.decrypt(data, 'wrong password', maxtime=0.1) # scrypt will throw an exception if the password is incorrect
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ scrypt.error: password is incorrect
+
+From these, one can make a simple password verifier using the following
+functions::
+
+ def randstr(length):
+ return ''.join(chr(random.randint(0,255)) for i in range(length))
+
+ def hash_password(password, maxtime=0.5, datalength=64):
+ return scrypt.encrypt(randstr(datalength), password, maxtime=maxtime)
+
+ def verify_password(hashed_password, guessed_password, maxtime=0.5):
+ try:
+ scrypt.decrypt(hashed_password, guessed_password, maxtime)
+ return True
+ except scrypt.error:
+ return False
+
+
+But, if you want output that is deterministic and constant in size,
+you can use the ``hash`` function::
+
+ >>> import scrypt
+ >>> h1 = scrypt.hash('password', 'random salt')
+ >>> len(h1) # The hash will be 64 bytes by default, but is overridable.
+ 64
+ >>> h1[:10]
+ '\xfe\x87\xf3hS\tUo\xcd\xc8'
+ >>> h2 = scrypt.hash('password', 'random salt')
+ >>> h1 == h2 # The hash function is deterministic
+ True
+
+
+Acknowledgements
+================
+
+Scrypt_ was created by Colin Percival and is licensed as 2-clause BSD.
+Since scrypt does not normally build as a shared library, I have included
+the source for the currently latest version of the library in this
+repository. When a new version arrives, I will update these sources.
+
+`Kelvin Wong`_ on Bitbucket provided changes to make the library
+available on Mac OS X 10.6 and earlier, as well as changes to make the
+library work more like the command-line version of scrypt by
+default. Kelvin also contributed with the unit tests, lots of cross
+platform testing and work on the ``hash`` function.
+
+Burstaholic_ on Bitbucket provided the necessary changes to make
+the library build on Windows.
+
+License
+=======
+
+This library is licensed under the same license as scrypt; 2-clause BSD.
+
+.. _scrypt: http://www.tarsnap.com/scrypt.html
+.. _Python: http://python.org
+.. _Burstaholic: https://bitbucket.org/Burstaholic
+.. _Kelvin Wong: https://bitbucket.org/kelvinwong_ca
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..38d89fb
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,29 @@
+python-scrypt (0.6.1-5) unstable; urgency=low
+
+ * Remove dependency on libscrypt0, it requires porting
+
+ -- Micah Anderson <micah@debian.org> Thu, 22 Aug 2013 16:01:24 -0400
+
+python-scrypt (0.6.1-4) unstable; urgency=low
+
+ * Update debian/copyright to fix missing DEP5 field
+
+ -- Micah Anderson <micah@debian.org> Tue, 13 Aug 2013 09:37:16 -0400
+
+python-scrypt (0.6.1-3) unstable; urgency=low
+
+ * Fix typo in libscrypt0 package dependency
+
+ -- Micah Anderson <micah@debian.org> Sat, 10 Aug 2013 21:39:40 +0200
+
+python-scrypt (0.6.1-2) unstable; urgency=low
+
+ * Add missing license information for embedded scrypt
+
+ -- Micah Anderson <micah@debian.org> Thu, 04 Jul 2013 12:03:29 -0400
+
+python-scrypt (0.6.1-1) unstable; urgency=low
+
+ * Initial package (Closes: #710464)
+
+ -- Micah Anderson <micah@debian.org> Thu, 30 May 2013 15:30:06 -0400
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..efa6172
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,20 @@
+Source: python-scrypt
+Maintainer: Micah Anderson <micah@debian.org>
+Section: python
+Priority: optional
+Build-Depends: python-all-dev (>= 2.6.6-3), debhelper (>= 9)
+Standards-Version: 3.9.4
+
+Package: python-scrypt
+Architecture: any
+Depends: ${misc:Depends}, ${python:Depends}, ${shlibs:Depends}
+Description: Python bindings for the scrypt key derivation function library
+ This is a set of Python bindings for the scrypt key derivation function.
+ .
+ Scrypt is useful when encrypting password as it is possible to specify a
+ minimum amount of time to use when encrypting and decrypting. If, for
+ example, a password takes 0.05 seconds to verify, a user won't notice the
+ slight delay when signing in, but doing a brute force search of several
+ billion passwords will take a considerable amount of time. This is in
+ contrast to more traditional hash functions such as MD5 or the SHA family
+ which can be implemented extremely fast on cheap hardware.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..4af456c
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,43 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: scrypt
+Upstream-Contact: mhallin@gmail.com
+Source: <http://bitbucket.org/mhallin/py-scrypt>
+
+Files: *
+Copyright: Copyright (C) 2010 Magnus Hallin
+License: BSD-2-Clause
+
+License: BSD-2-Clause
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ .
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+Files: scrypt-1.1.6/*
+Copyright: Copyright 2005,2007-2009 Colin Percival
+License: BSD-2-Clause
+
+Files: debian/*
+Copyright: Copyright 2013 Micah Anderson <micah@leap.se>
+License: GPL-3+
+
+License: GPL-3+
+ On Debian systems, the complete text of the GNU General
+ Public License can be found in `/usr/share/common-licenses/GPL'.
diff --git a/debian/python-scrypt.lintian-overrides b/debian/python-scrypt.lintian-overrides
new file mode 100644
index 0000000..472a1d6
--- /dev/null
+++ b/debian/python-scrypt.lintian-overrides
@@ -0,0 +1,4 @@
+# Only the debian packaging is covered by the GPL, the rest is a 2-clause BSD
+# tell lintian to not complain:
+python-scrypt: possible-gpl-code-linked-with-openssl
+
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..bcebae9
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+
+%:
+ dh $@ --with python2 --buildsystem=python_distutils
+
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/scrypt-1.1.6/config.h b/scrypt-1.1.6/config.h
new file mode 100644
index 0000000..f1e6fd6
--- /dev/null
+++ b/scrypt-1.1.6/config.h
@@ -0,0 +1,99 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define to 1 if you have the declaration of `be64enc', and to 0 if you
+ don't. */
+#define HAVE_DECL_BE64ENC 0
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+/* #undef HAVE_LIBRT */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `posix_memalign' function. */
+/* #undef HAVE_POSIX_MEMALIGN */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct sysinfo'. */
+/* #undef HAVE_STRUCT_SYSINFO */
+
+/* Define to 1 if `mem_unit' is member of `struct sysinfo'. */
+/* #undef HAVE_STRUCT_SYSINFO_MEM_UNIT */
+
+/* Define to 1 if `totalram' is member of `struct sysinfo'. */
+/* #undef HAVE_STRUCT_SYSINFO_TOTALRAM */
+
+/* Define to 1 if the OS has a hw.usermem sysctl */
+/* #undef HAVE_SYSCTL_HW_USERMEM */
+
+/* Define to 1 if you have the `sysinfo' function. */
+/* #undef HAVE_SYSINFO */
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+/* #undef HAVE_SYS_ENDIAN_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysinfo.h> header file. */
+/* #undef HAVE_SYS_SYSINFO_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "scrypt"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "scrypt"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "scrypt 1.1.6"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "scrypt"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.1.6"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "1.1.6"
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
diff --git a/scrypt-1.1.6/lib/crypto/crypto_aesctr.c b/scrypt-1.1.6/lib/crypto/crypto_aesctr.c
new file mode 100644
index 0000000..00db8f0
--- /dev/null
+++ b/scrypt-1.1.6/lib/crypto/crypto_aesctr.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright 2007-2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <openssl/aes.h>
+
+#include "sysendian.h"
+
+#include "crypto_aesctr.h"
+
+struct crypto_aesctr {
+ AES_KEY * key;
+ uint64_t nonce;
+ uint64_t bytectr;
+ uint8_t buf[16];
+};
+
+/**
+ * crypto_aesctr_init(key, nonce):
+ * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided
+ * expanded key and nonce. The key provided must remain valid for the
+ * lifetime of the stream.
+ */
+struct crypto_aesctr *
+crypto_aesctr_init(AES_KEY * key, uint64_t nonce)
+{
+ struct crypto_aesctr * stream;
+
+ /* Allocate memory. */
+ if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL)
+ goto err0;
+
+ /* Initialize values. */
+ stream->key = key;
+ stream->nonce = nonce;
+ stream->bytectr = 0;
+
+ /* Success! */
+ return (stream);
+
+err0:
+ /* Failure! */
+ return (NULL);
+}
+
+/**
+ * crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
+ * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
+ * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers
+ * ${inbuf} and ${outbuf} overlap, they must be identical.
+ */
+void
+crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf,
+ uint8_t * outbuf, size_t buflen)
+{
+ uint8_t pblk[16];
+ size_t pos;
+ int bytemod;
+
+ for (pos = 0; pos < buflen; pos++) {
+ /* How far through the buffer are we? */
+ bytemod = stream->bytectr % 16;
+
+ /* Generate a block of cipherstream if needed. */
+ if (bytemod == 0) {
+ be64enc(pblk, stream->nonce);
+ be64enc(pblk + 8, stream->bytectr / 16);
+ AES_encrypt(pblk, stream->buf, stream->key);
+ }
+
+ /* Encrypt a byte. */
+ outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod];
+
+ /* Move to the next byte of cipherstream. */
+ stream->bytectr += 1;
+ }
+}
+
+/**
+ * crypto_aesctr_free(stream):
+ * Free the provided stream object.
+ */
+void
+crypto_aesctr_free(struct crypto_aesctr * stream)
+{
+ int i;
+
+ /* Zero potentially sensitive information. */
+ for (i = 0; i < 16; i++)
+ stream->buf[i] = 0;
+ stream->bytectr = stream->nonce = 0;
+
+ /* Free the stream. */
+ free(stream);
+}
diff --git a/scrypt-1.1.6/lib/crypto/crypto_aesctr.h b/scrypt-1.1.6/lib/crypto/crypto_aesctr.h
new file mode 100644
index 0000000..b50398f
--- /dev/null
+++ b/scrypt-1.1.6/lib/crypto/crypto_aesctr.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _CRYPTO_AESCTR_H_
+#define _CRYPTO_AESCTR_H_
+
+#include <stdint.h>
+
+#include <openssl/aes.h>
+
+/**
+ * crypto_aesctr_init(key, nonce):
+ * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided
+ * expanded key and nonce. The key provided must remain valid for the
+ * lifetime of the stream.
+ */
+struct crypto_aesctr * crypto_aesctr_init(AES_KEY *, uint64_t);
+
+/**
+ * crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
+ * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
+ * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers
+ * ${inbuf} and ${outbuf} overlap, they must be identical.
+ */
+void crypto_aesctr_stream(struct crypto_aesctr *, const uint8_t *,
+ uint8_t *, size_t);
+
+/**
+ * crypto_aesctr_free(stream):
+ * Free the provided stream object.
+ */
+void crypto_aesctr_free(struct crypto_aesctr *);
+
+#endif /* !_CRYPTO_AESCTR_H_ */
diff --git a/scrypt-1.1.6/lib/crypto/crypto_scrypt-nosse.c b/scrypt-1.1.6/lib/crypto/crypto_scrypt-nosse.c
new file mode 100644
index 0000000..a253379
--- /dev/null
+++ b/scrypt-1.1.6/lib/crypto/crypto_scrypt-nosse.c
@@ -0,0 +1,345 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <sys/types.h>
+
+#ifndef _WIN32
+#include <sys/mman.h>
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sha256.h"
+#include "sysendian.h"
+
+#include "crypto_scrypt.h"
+
+static void blkcpy(void *, void *, size_t);
+static void blkxor(void *, void *, size_t);
+static void salsa20_8(uint32_t[16]);
+static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t);
+static uint64_t integerify(void *, size_t);
+static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *);
+
+static void
+blkcpy(void * dest, void * src, size_t len)
+{
+ size_t * D = dest;
+ size_t * S = src;
+ size_t L = len / sizeof(size_t);
+ size_t i;
+
+ for (i = 0; i < L; i++)
+ D[i] = S[i];
+}
+
+static void
+blkxor(void * dest, void * src, size_t len)
+{
+ size_t * D = dest;
+ size_t * S = src;
+ size_t L = len / sizeof(size_t);
+ size_t i;
+
+ for (i = 0; i < L; i++)
+ D[i] ^= S[i];
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(uint32_t B[16])
+{
+ uint32_t x[16];
+ size_t i;
+
+ blkcpy(x, B, 64);
+ for (i = 0; i < 8; i += 2) {
+#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+ /* Operate on columns. */
+ x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
+ x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
+
+ x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
+ x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
+
+ x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
+ x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
+
+ x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
+ x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
+
+ /* Operate on rows. */
+ x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
+ x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
+
+ x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
+ x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
+
+ x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
+ x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
+
+ x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
+ x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
+#undef R
+ }
+ for (i = 0; i < 16; i++)
+ B[i] += x[i];
+}
+
+/**
+ * blockmix_salsa8(Bin, Bout, X, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size. The
+ * temporary space X must be 64 bytes.
+ */
+static void
+blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
+{
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
+
+ /* 2: for i = 0 to 2r - 1 do */
+ for (i = 0; i < 2 * r; i += 2) {
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor(X, &Bin[i * 16], 64);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy(&Bout[i * 8], X, 64);
+
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor(X, &Bin[i * 16 + 16], 64);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy(&Bout[i * 8 + r * 16], X, 64);
+ }
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static uint64_t
+integerify(void * B, size_t r)
+{
+ uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);
+
+ return (((uint64_t)(X[1]) << 32) + X[0]);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
+{
+ uint32_t * X = XY;
+ uint32_t * Y = &XY[32 * r];
+ uint32_t * Z = &XY[64 * r];
+ uint64_t i;
+ uint64_t j;
+ size_t k;
+
+ /* 1: X <-- B */
+ for (k = 0; k < 32 * r; k++)
+ X[k] = le32dec(&B[4 * k]);
+
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 3: V_i <-- X */
+ blkcpy(&V[i * (32 * r)], X, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 3: V_i <-- X */
+ blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(Y, X, Z, r);
+ }
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor(X, &V[j * (32 * r)], 128 * r);
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(Y, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor(Y, &V[j * (32 * r)], 128 * r);
+ blockmix_salsa8(Y, X, Z, r);
+ }
+
+ /* 10: B' <-- X */
+ for (k = 0; k < 32 * r; k++)
+ le32enc(&B[4 * k], X[k]);
+}
+
+/**
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
+ uint8_t * buf, size_t buflen)
+{
+ void * B0, * V0, * XY0;
+ uint8_t * B;
+ uint32_t * V;
+ uint32_t * XY;
+ uint32_t i;
+
+ /* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ goto err0;
+ }
+#endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
+ errno = EFBIG;
+ goto err0;
+ }
+ if (((N & (N - 1)) != 0) || (N == 0)) {
+ errno = EINVAL;
+ goto err0;
+ }
+ if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+#endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ goto err0;
+ }
+
+ /* Allocate memory. */
+#ifdef _WIN32
+#undef HAVE_POSIX_MEMALIGN
+#endif
+
+#ifdef HAVE_POSIX_MEMALIGN
+ if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
+ goto err0;
+ B = (uint8_t *)(B0);
+ if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
+ goto err1;
+ XY = (uint32_t *)(XY0);
+#ifndef MAP_ANON
+ if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
+ goto err2;
+ V = (uint32_t *)(V0);
+#endif
+#else
+ if ((B0 = malloc(128 * r * p + 63)) == NULL)
+ goto err0;
+ B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
+ if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
+ goto err1;
+ XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
+#ifndef MAP_ANON
+ if ((V0 = malloc(128 * r * N + 63)) == NULL)
+ goto err2;
+ V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
+#endif
+#endif
+#ifdef MAP_ANON
+ if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
+#ifdef MAP_NOCORE
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
+#else
+ MAP_ANON | MAP_PRIVATE,
+#endif
+ -1, 0)) == MAP_FAILED)
+ goto err2;
+ V = (uint32_t *)(V0);
+#endif
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_scrypt_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[i * 128 * r], r, N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_scrypt_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
+
+ /* Free memory. */
+#ifdef MAP_ANON
+ if (munmap(V0, 128 * r * N))
+ goto err2;
+#else
+ free(V0);
+#endif
+ free(XY0);
+ free(B0);
+
+ /* Success! */
+ return (0);
+
+err2:
+ free(XY0);
+err1:
+ free(B0);
+err0:
+ /* Failure! */
+ return (-1);
+}
diff --git a/scrypt-1.1.6/lib/crypto/crypto_scrypt.h b/scrypt-1.1.6/lib/crypto/crypto_scrypt.h
new file mode 100644
index 0000000..f72e1f4
--- /dev/null
+++ b/scrypt-1.1.6/lib/crypto/crypto_scrypt.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _CRYPTO_SCRYPT_H_
+#define _CRYPTO_SCRYPT_H_
+
+#include <stdint.h>
+
+/**
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
+ uint32_t, uint32_t, uint8_t *, size_t);
+
+#endif /* !_CRYPTO_SCRYPT_H_ */
diff --git a/scrypt-1.1.6/lib/crypto/sha256.c b/scrypt-1.1.6/lib/crypto/sha256.c
new file mode 100644
index 0000000..2812cf5
--- /dev/null
+++ b/scrypt-1.1.6/lib/crypto/sha256.c
@@ -0,0 +1,412 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "scrypt_platform.h"
+
+#include <sys/types.h>
+
+#include <stdint.h>
+#include <string.h>
+
+#include "sysendian.h"
+
+#include "sha256.h"
+
+/*
+ * Encode a length len/4 vector of (uint32_t) into a length len vector of
+ * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
+ */
+static void
+be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 4; i++)
+ be32enc(dst + i * 4, src[i]);
+}
+
+/*
+ * Decode a big-endian length len vector of (unsigned char) into a length
+ * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
+ */
+static void
+be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 4; i++)
+ dst[i] = be32dec(src + i * 4);
+}
+
+/* Elementary functions used by scrypt_SHA256 */
+#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
+#define Maj(x, y, z) ((x & (y | z)) | (y & z))
+#define SHR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
+#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
+#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
+
+/* scrypt_SHA256 round function */
+#define RND(a, b, c, d, e, f, g, h, k) \
+ t0 = h + S1(e) + Ch(e, f, g) + k; \
+ t1 = S0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+/* Adjusted round function for rotating state */
+#define RNDr(S, W, i, k) \
+ RND(S[(64 - i) % 8], S[(65 - i) % 8], \
+ S[(66 - i) % 8], S[(67 - i) % 8], \
+ S[(68 - i) % 8], S[(69 - i) % 8], \
+ S[(70 - i) % 8], S[(71 - i) % 8], \
+ W[i] + k)
+
+/*
+ * scrypt_SHA256 block compression function. The 256-bit state is transformed via
+ * the 512-bit input block to produce a new state.
+ */
+static void
+scrypt_SHA256_Transform(uint32_t * state, const unsigned char block[64])
+{
+ uint32_t W[64];
+ uint32_t S[8];
+ uint32_t t0, t1;
+ int i;
+
+ /* 1. Prepare message schedule W. */
+ be32dec_vect(W, block, 64);
+ for (i = 16; i < 64; i++)
+ W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
+
+ /* 2. Initialize working variables. */
+ memcpy(S, state, 32);
+
+ /* 3. Mix. */
+ RNDr(S, W, 0, 0x428a2f98);
+ RNDr(S, W, 1, 0x71374491);
+ RNDr(S, W, 2, 0xb5c0fbcf);
+ RNDr(S, W, 3, 0xe9b5dba5);
+ RNDr(S, W, 4, 0x3956c25b);
+ RNDr(S, W, 5, 0x59f111f1);
+ RNDr(S, W, 6, 0x923f82a4);
+ RNDr(S, W, 7, 0xab1c5ed5);
+ RNDr(S, W, 8, 0xd807aa98);
+ RNDr(S, W, 9, 0x12835b01);
+ RNDr(S, W, 10, 0x243185be);
+ RNDr(S, W, 11, 0x550c7dc3);
+ RNDr(S, W, 12, 0x72be5d74);
+ RNDr(S, W, 13, 0x80deb1fe);
+ RNDr(S, W, 14, 0x9bdc06a7);
+ RNDr(S, W, 15, 0xc19bf174);
+ RNDr(S, W, 16, 0xe49b69c1);
+ RNDr(S, W, 17, 0xefbe4786);
+ RNDr(S, W, 18, 0x0fc19dc6);
+ RNDr(S, W, 19, 0x240ca1cc);
+ RNDr(S, W, 20, 0x2de92c6f);
+ RNDr(S, W, 21, 0x4a7484aa);
+ RNDr(S, W, 22, 0x5cb0a9dc);
+ RNDr(S, W, 23, 0x76f988da);
+ RNDr(S, W, 24, 0x983e5152);
+ RNDr(S, W, 25, 0xa831c66d);
+ RNDr(S, W, 26, 0xb00327c8);
+ RNDr(S, W, 27, 0xbf597fc7);
+ RNDr(S, W, 28, 0xc6e00bf3);
+ RNDr(S, W, 29, 0xd5a79147);
+ RNDr(S, W, 30, 0x06ca6351);
+ RNDr(S, W, 31, 0x14292967);
+ RNDr(S, W, 32, 0x27b70a85);
+ RNDr(S, W, 33, 0x2e1b2138);
+ RNDr(S, W, 34, 0x4d2c6dfc);
+ RNDr(S, W, 35, 0x53380d13);
+ RNDr(S, W, 36, 0x650a7354);
+ RNDr(S, W, 37, 0x766a0abb);
+ RNDr(S, W, 38, 0x81c2c92e);
+ RNDr(S, W, 39, 0x92722c85);
+ RNDr(S, W, 40, 0xa2bfe8a1);
+ RNDr(S, W, 41, 0xa81a664b);
+ RNDr(S, W, 42, 0xc24b8b70);
+ RNDr(S, W, 43, 0xc76c51a3);
+ RNDr(S, W, 44, 0xd192e819);
+ RNDr(S, W, 45, 0xd6990624);
+ RNDr(S, W, 46, 0xf40e3585);
+ RNDr(S, W, 47, 0x106aa070);
+ RNDr(S, W, 48, 0x19a4c116);
+ RNDr(S, W, 49, 0x1e376c08);
+ RNDr(S, W, 50, 0x2748774c);
+ RNDr(S, W, 51, 0x34b0bcb5);
+ RNDr(S, W, 52, 0x391c0cb3);
+ RNDr(S, W, 53, 0x4ed8aa4a);
+ RNDr(S, W, 54, 0x5b9cca4f);
+ RNDr(S, W, 55, 0x682e6ff3);
+ RNDr(S, W, 56, 0x748f82ee);
+ RNDr(S, W, 57, 0x78a5636f);
+ RNDr(S, W, 58, 0x84c87814);
+ RNDr(S, W, 59, 0x8cc70208);
+ RNDr(S, W, 60, 0x90befffa);
+ RNDr(S, W, 61, 0xa4506ceb);
+ RNDr(S, W, 62, 0xbef9a3f7);
+ RNDr(S, W, 63, 0xc67178f2);
+
+ /* 4. Mix local working variables into global state */
+ for (i = 0; i < 8; i++)
+ state[i] += S[i];
+
+ /* Clean the stack. */
+ memset(W, 0, 256);
+ memset(S, 0, 32);
+ t0 = t1 = 0;
+}
+
+static unsigned char PAD[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* Add padding and terminating bit-count. */
+static void
+scrypt_SHA256_Pad(scrypt_SHA256_CTX * ctx)
+{
+ unsigned char len[8];
+ uint32_t r, plen;
+
+ /*
+ * Convert length to a vector of bytes -- we do this now rather
+ * than later because the length will change after we pad.
+ */
+ be32enc_vect(len, ctx->count, 8);
+
+ /* Add 1--64 bytes so that the resulting length is 56 mod 64 */
+ r = (ctx->count[1] >> 3) & 0x3f;
+ plen = (r < 56) ? (56 - r) : (120 - r);
+ scrypt_SHA256_Update(ctx, PAD, (size_t)plen);
+
+ /* Add the terminating bit-count */
+ scrypt_SHA256_Update(ctx, len, 8);
+}
+
+/* SHA-256 initialization. Begins a SHA-256 operation. */
+void
+scrypt_SHA256_Init(scrypt_SHA256_CTX * ctx)
+{
+
+ /* Zero bits processed so far */
+ ctx->count[0] = ctx->count[1] = 0;
+
+ /* Magic initialization constants */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+}
+
+/* Add bytes into the hash */
+void
+scrypt_SHA256_Update(scrypt_SHA256_CTX * ctx, const void *in, size_t len)
+{
+ uint32_t bitlen[2];
+ uint32_t r;
+ const unsigned char *src = in;
+
+ /* Number of bytes left in the buffer from previous updates */
+ r = (ctx->count[1] >> 3) & 0x3f;
+
+ /* Convert the length into a number of bits */
+ bitlen[1] = ((uint32_t)len) << 3;
+ bitlen[0] = (uint32_t)(len >> 29);
+
+ /* Update number of bits */
+ if ((ctx->count[1] += bitlen[1]) < bitlen[1])
+ ctx->count[0]++;
+ ctx->count[0] += bitlen[0];
+
+ /* Handle the case where we don't need to perform any transforms */
+ if (len < 64 - r) {
+ memcpy(&ctx->buf[r], src, len);
+ return;
+ }
+
+ /* Finish the current block */
+ memcpy(&ctx->buf[r], src, 64 - r);
+ scrypt_SHA256_Transform(ctx->state, ctx->buf);
+ src += 64 - r;
+ len -= 64 - r;
+
+ /* Perform complete blocks */
+ while (len >= 64) {
+ scrypt_SHA256_Transform(ctx->state, src);
+ src += 64;
+ len -= 64;
+ }
+
+ /* Copy left over data into buffer */
+ memcpy(ctx->buf, src, len);
+}
+
+/*
+ * SHA-256 finalization. Pads the input data, exports the hash value,
+ * and clears the context state.
+ */
+void
+scrypt_SHA256_Final(unsigned char digest[32], scrypt_SHA256_CTX * ctx)
+{
+
+ /* Add padding */
+ scrypt_SHA256_Pad(ctx);
+
+ /* Write the hash */
+ be32enc_vect(digest, ctx->state, 32);
+
+ /* Clear the context state */
+ memset((void *)ctx, 0, sizeof(*ctx));
+}
+
+/* Initialize an HMAC-scrypt_SHA256 operation with the given key. */
+void
+HMAC_scrypt_SHA256_Init(HMAC_scrypt_SHA256_CTX * ctx, const void * _K, size_t Klen)
+{
+ unsigned char pad[64];
+ unsigned char khash[32];
+ const unsigned char * K = _K;
+ size_t i;
+
+ /* If Klen > 64, the key is really scrypt_SHA256(K). */
+ if (Klen > 64) {
+ scrypt_SHA256_Init(&ctx->ictx);
+ scrypt_SHA256_Update(&ctx->ictx, K, Klen);
+ scrypt_SHA256_Final(khash, &ctx->ictx);
+ K = khash;
+ Klen = 32;
+ }
+
+ /* Inner scrypt_SHA256 operation is scrypt_SHA256(K xor [block of 0x36] || data). */
+ scrypt_SHA256_Init(&ctx->ictx);
+ memset(pad, 0x36, 64);
+ for (i = 0; i < Klen; i++)
+ pad[i] ^= K[i];
+ scrypt_SHA256_Update(&ctx->ictx, pad, 64);
+
+ /* Outer scrypt_SHA256 operation is scrypt_SHA256(K xor [block of 0x5c] || hash). */
+ scrypt_SHA256_Init(&ctx->octx);
+ memset(pad, 0x5c, 64);
+ for (i = 0; i < Klen; i++)
+ pad[i] ^= K[i];
+ scrypt_SHA256_Update(&ctx->octx, pad, 64);
+
+ /* Clean the stack. */
+ memset(khash, 0, 32);
+}
+
+/* Add bytes to the HMAC-scrypt_SHA256 operation. */
+void
+HMAC_scrypt_SHA256_Update(HMAC_scrypt_SHA256_CTX * ctx, const void *in, size_t len)
+{
+
+ /* Feed data to the inner scrypt_SHA256 operation. */
+ scrypt_SHA256_Update(&ctx->ictx, in, len);
+}
+
+/* Finish an HMAC-scrypt_SHA256 operation. */
+void
+HMAC_scrypt_SHA256_Final(unsigned char digest[32], HMAC_scrypt_SHA256_CTX * ctx)
+{
+ unsigned char ihash[32];
+
+ /* Finish the inner scrypt_SHA256 operation. */
+ scrypt_SHA256_Final(ihash, &ctx->ictx);
+
+ /* Feed the inner hash to the outer scrypt_SHA256 operation. */
+ scrypt_SHA256_Update(&ctx->octx, ihash, 32);
+
+ /* Finish the outer scrypt_SHA256 operation. */
+ scrypt_SHA256_Final(digest, &ctx->octx);
+
+ /* Clean the stack. */
+ memset(ihash, 0, 32);
+}
+
+/**
+ * PBKDF2_scrypt_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-scrypt_SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void
+PBKDF2_scrypt_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
+ size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
+{
+ HMAC_scrypt_SHA256_CTX PShctx, hctx;
+ size_t i;
+ uint8_t ivec[4];
+ uint8_t U[32];
+ uint8_t T[32];
+ uint64_t j;
+ int k;
+ size_t clen;
+
+ /* Compute HMAC state after processing P and S. */
+ HMAC_scrypt_SHA256_Init(&PShctx, passwd, passwdlen);
+ HMAC_scrypt_SHA256_Update(&PShctx, salt, saltlen);
+
+ /* Iterate through the blocks. */
+ for (i = 0; i * 32 < dkLen; i++) {
+ /* Generate INT(i + 1). */
+ be32enc(ivec, (uint32_t)(i + 1));
+
+ /* Compute U_1 = PRF(P, S || INT(i)). */
+ memcpy(&hctx, &PShctx, sizeof(HMAC_scrypt_SHA256_CTX));
+ HMAC_scrypt_SHA256_Update(&hctx, ivec, 4);
+ HMAC_scrypt_SHA256_Final(U, &hctx);
+
+ /* T_i = U_1 ... */
+ memcpy(T, U, 32);
+
+ for (j = 2; j <= c; j++) {
+ /* Compute U_j. */
+ HMAC_scrypt_SHA256_Init(&hctx, passwd, passwdlen);
+ HMAC_scrypt_SHA256_Update(&hctx, U, 32);
+ HMAC_scrypt_SHA256_Final(U, &hctx);
+
+ /* ... xor U_j ... */
+ for (k = 0; k < 32; k++)
+ T[k] ^= U[k];
+ }
+
+ /* Copy as many bytes as necessary into buf. */
+ clen = dkLen - i * 32;
+ if (clen > 32)
+ clen = 32;
+ memcpy(&buf[i * 32], T, clen);
+ }
+
+ /* Clean PShctx, since we never called _Final on it. */
+ memset(&PShctx, 0, sizeof(HMAC_scrypt_SHA256_CTX));
+}
diff --git a/scrypt-1.1.6/lib/crypto/sha256.h b/scrypt-1.1.6/lib/crypto/sha256.h
new file mode 100644
index 0000000..74ab0fd
--- /dev/null
+++ b/scrypt-1.1.6/lib/crypto/sha256.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $
+ */
+
+#ifndef _scrypt_SHA256_H_
+#define _scrypt_SHA256_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+typedef struct scrypt_SHA256Context {
+ uint32_t state[8];
+ uint32_t count[2];
+ unsigned char buf[64];
+} scrypt_SHA256_CTX;
+
+typedef struct HMAC_scrypt_SHA256Context {
+ scrypt_SHA256_CTX ictx;
+ scrypt_SHA256_CTX octx;
+} HMAC_scrypt_SHA256_CTX;
+
+void scrypt_SHA256_Init(scrypt_SHA256_CTX *);
+void scrypt_SHA256_Update(scrypt_SHA256_CTX *, const void *, size_t);
+void scrypt_SHA256_Final(unsigned char [32], scrypt_SHA256_CTX *);
+void HMAC_scrypt_SHA256_Init(HMAC_scrypt_SHA256_CTX *, const void *, size_t);
+void HMAC_scrypt_SHA256_Update(HMAC_scrypt_SHA256_CTX *, const void *, size_t);
+void HMAC_scrypt_SHA256_Final(unsigned char [32], HMAC_scrypt_SHA256_CTX *);
+
+/**
+ * PBKDF2_scrypt_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-scrypt_SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void PBKDF2_scrypt_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
+ uint64_t, uint8_t *, size_t);
+
+#endif /* !_scrypt_SHA256_H_ */
diff --git a/scrypt-1.1.6/lib/scryptenc/scryptenc.c b/scrypt-1.1.6/lib/scryptenc/scryptenc.c
new file mode 100644
index 0000000..c16a82c
--- /dev/null
+++ b/scrypt-1.1.6/lib/scryptenc/scryptenc.c
@@ -0,0 +1,633 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/aes.h>
+
+#include "crypto_aesctr.h"
+#include "crypto_scrypt.h"
+#include "memlimit.h"
+#include "scryptenc_cpuperf.h"
+#include "sha256.h"
+#include "sysendian.h"
+
+#include "scryptenc.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#include <Wincrypt.h>
+#endif
+
+#define ENCBLOCK 65536
+
+static int pickparams(size_t, double, double,
+ int *, uint32_t *, uint32_t *);
+static int checkparams(size_t, double, double, int, uint32_t, uint32_t);
+static int getsalt(uint8_t[32]);
+
+static int
+pickparams(size_t maxmem, double maxmemfrac, double maxtime,
+ int * logN, uint32_t * r, uint32_t * p)
+{
+ size_t memlimit;
+ double opps;
+ double opslimit;
+ double maxN, maxrp;
+ int rc;
+
+ /* Figure out how much memory to use. */
+ if (memtouse(maxmem, maxmemfrac, &memlimit))
+ return (1);
+
+ /* Figure out how fast the CPU is. */
+ if ((rc = scryptenc_cpuperf(&opps)) != 0)
+ return (rc);
+ opslimit = opps * maxtime;
+
+ /* Allow a minimum of 2^15 salsa20/8 cores. */
+ if (opslimit < 32768)
+ opslimit = 32768;
+
+ /* Fix r = 8 for now. */
+ *r = 8;
+
+ /*
+ * The memory limit requires that 128Nr <= memlimit, while the CPU
+ * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32,
+ * opslimit imposes the stronger limit on N.
+ */
+#ifdef DEBUG
+ fprintf(stderr, "Requiring 128Nr <= %u, 4Nrp <= %f\n",
+ memlimit, opslimit);
+#endif
+ if (opslimit < memlimit/32) {
+ /* Set p = 1 and choose N based on the CPU limit. */
+ *p = 1;
+ maxN = opslimit / (*r * 4);
+ for (*logN = 1; *logN < 63; *logN += 1) {
+ if ((uint64_t)(1) << *logN > maxN / 2)
+ break;
+ }
+ } else {
+ /* Set N based on the memory limit. */
+ maxN = memlimit / (*r * 128);
+ for (*logN = 1; *logN < 63; *logN += 1) {
+ if ((uint64_t)(1) << *logN > maxN / 2)
+ break;
+ }
+
+ /* Choose p based on the CPU limit. */
+ maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN);
+ if (maxrp > 0x3fffffff)
+ maxrp = 0x3fffffff;
+ *p = (uint32_t)(maxrp) / *r;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "N = %u r = %d p = %d\n",
+ (size_t)(1) << *logN, (int)(*r), (int)(*p));
+#endif
+
+ /* Success! */
+ return (0);
+}
+
+static int
+checkparams(size_t maxmem, double maxmemfrac, double maxtime,
+ int logN, uint32_t r, uint32_t p)
+{
+ size_t memlimit;
+ double opps;
+ double opslimit;
+ uint64_t N;
+ int rc;
+
+ /* Figure out the maximum amount of memory we can use. */
+ if (memtouse(maxmem, maxmemfrac, &memlimit))
+ return (1);
+
+ /* Figure out how fast the CPU is. */
+ if ((rc = scryptenc_cpuperf(&opps)) != 0)
+ return (rc);
+ opslimit = opps * maxtime;
+
+ /* Sanity-check values. */
+ if ((logN < 1) || (logN > 63))
+ return (7);
+ if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000)
+ return (7);
+
+ /* Check limits. */
+ N = (uint64_t)(1) << logN;
+ if ((memlimit / N) / r < 128)
+ return (9);
+ if ((opslimit / N) / (r * p) < 4)
+ return (10);
+
+ /* Success! */
+ return (0);
+}
+
+static int
+getsalt(uint8_t salt[32])
+{
+ int fd;
+ ssize_t lenread;
+ uint8_t * buf = salt;
+ size_t buflen = 32;
+
+#ifndef _WIN32
+ /* Open /dev/urandom. */
+ if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
+ goto err0;
+
+ /* Read bytes until we have filled the buffer. */
+ while (buflen > 0) {
+ if ((lenread = read(fd, buf, buflen)) == -1)
+ goto err1;
+
+ /* The random device should never EOF. */
+ if (lenread == 0)
+ goto err1;
+
+ /* We're partly done. */
+ buf += lenread;
+ buflen -= lenread;
+ }
+
+ /* Close the device. */
+ while (close(fd) == -1) {
+ if (errno != EINTR)
+ goto err0;
+ }
+
+ /* Success! */
+ return (0);
+
+err1:
+ close(fd);
+err0:
+ /* Failure! */
+ return (4);
+#else
+ HCRYPTPROV context;
+ DWORD error;
+
+ if(CryptAcquireContext(&context, NULL, NULL, PROV_RSA_AES, 0) == NTE_BAD_KEYSET)
+ {
+ if(!CryptAcquireContext(&context, NULL, NULL, PROV_RSA_AES, CRYPT_NEWKEYSET))
+ {
+ error = GetLastError();
+ printf("%x", error);
+ return (14);
+ }
+ }
+
+ if(CryptGenRandom(context, 32, buf))
+ {
+ buf += 32;
+ return (0);
+ }
+ else{return(15);}
+#endif
+}
+
+static int
+scryptenc_setup(uint8_t header[96], uint8_t dk[64],
+ const uint8_t * passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime)
+{
+ uint8_t salt[32];
+ uint8_t hbuf[32];
+ int logN;
+ uint64_t N;
+ uint32_t r;
+ uint32_t p;
+ scrypt_SHA256_CTX ctx;
+ uint8_t * key_hmac = &dk[32];
+ HMAC_scrypt_SHA256_CTX hctx;
+ int rc;
+
+ /* Pick values for N, r, p. */
+ if ((rc = pickparams(maxmem, maxmemfrac, maxtime,
+ &logN, &r, &p)) != 0)
+ return (rc);
+ N = (uint64_t)(1) << logN;
+
+ /* Get some salt. */
+ if ((rc = getsalt(salt)) != 0)
+ return (rc);
+
+ /* Generate the derived keys. */
+ if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
+ return (3);
+
+ /* Construct the file header. */
+ memcpy(header, "scrypt", 6);
+ header[6] = 0;
+ header[7] = logN;
+ be32enc(&header[8], r);
+ be32enc(&header[12], p);
+ memcpy(&header[16], salt, 32);
+
+ /* Add header checksum. */
+ scrypt_SHA256_Init(&ctx);
+ scrypt_SHA256_Update(&ctx, header, 48);
+ scrypt_SHA256_Final(hbuf, &ctx);
+ memcpy(&header[48], hbuf, 16);
+
+ /* Add header signature (used for verifying password). */
+ HMAC_scrypt_SHA256_Init(&hctx, key_hmac, 32);
+ HMAC_scrypt_SHA256_Update(&hctx, header, 64);
+ HMAC_scrypt_SHA256_Final(hbuf, &hctx);
+ memcpy(&header[64], hbuf, 32);
+
+ /* Success! */
+ return (0);
+}
+
+static int
+scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
+ const uint8_t * passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime)
+{
+ uint8_t salt[32];
+ uint8_t hbuf[32];
+ int logN;
+ uint32_t r;
+ uint32_t p;
+ uint64_t N;
+ scrypt_SHA256_CTX ctx;
+ uint8_t * key_hmac = &dk[32];
+ HMAC_scrypt_SHA256_CTX hctx;
+ int rc;
+
+ /* Parse N, r, p, salt. */
+ logN = header[7];
+ r = be32dec(&header[8]);
+ p = be32dec(&header[12]);
+ memcpy(salt, &header[16], 32);
+
+ /* Verify header checksum. */
+ scrypt_SHA256_Init(&ctx);
+ scrypt_SHA256_Update(&ctx, header, 48);
+ scrypt_SHA256_Final(hbuf, &ctx);
+ if (memcmp(&header[48], hbuf, 16))
+ return (7);
+
+ /*
+ * Check whether the provided parameters are valid and whether the
+ * key derivation function can be computed within the allowed memory
+ * and CPU time.
+ */
+ if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p)) != 0)
+ return (rc);
+
+ /* Compute the derived keys. */
+ N = (uint64_t)(1) << logN;
+ if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
+ return (3);
+
+ /* Check header signature (i.e., verify password). */
+ HMAC_scrypt_SHA256_Init(&hctx, key_hmac, 32);
+ HMAC_scrypt_SHA256_Update(&hctx, header, 64);
+ HMAC_scrypt_SHA256_Final(hbuf, &hctx);
+ if (memcmp(hbuf, &header[64], 32))
+ return (11);
+
+ /* Success! */
+ return (0);
+}
+
+/**
+ * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
+ * bytes to outbuf.
+ */
+int
+scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
+ const uint8_t * passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime)
+{
+ uint8_t dk[64];
+ uint8_t hbuf[32];
+ uint8_t header[96];
+ uint8_t * key_enc = dk;
+ uint8_t * key_hmac = &dk[32];
+ int rc;
+ HMAC_scrypt_SHA256_CTX hctx;
+ AES_KEY key_enc_exp;
+ struct crypto_aesctr * AES;
+
+ /* Generate the header and derived key. */
+ if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
+ maxmem, maxmemfrac, maxtime)) != 0)
+ return (rc);
+
+ /* Copy header into output buffer. */
+ memcpy(outbuf, header, 96);
+
+ /* Encrypt data. */
+ if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
+ return (5);
+ if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
+ return (6);
+ crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen);
+ crypto_aesctr_free(AES);
+
+ /* Add signature. */
+ HMAC_scrypt_SHA256_Init(&hctx, key_hmac, 32);
+ HMAC_scrypt_SHA256_Update(&hctx, outbuf, 96 + inbuflen);
+ HMAC_scrypt_SHA256_Final(hbuf, &hctx);
+ memcpy(&outbuf[96 + inbuflen], hbuf, 32);
+
+ /* Zero sensitive data. */
+ memset(dk, 0, 64);
+ memset(&key_enc_exp, 0, sizeof(AES_KEY));
+
+ /* Success! */
+ return (0);
+}
+
+/**
+ * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Decrypt inbuflen bytes fro inbuf, writing the result into outbuf and the
+ * decrypted data length to outlen. The allocated length of outbuf must
+ * be at least inbuflen.
+ */
+int
+scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
+ size_t * outlen, const uint8_t * passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime)
+{
+ uint8_t hbuf[32];
+ uint8_t dk[64];
+ uint8_t * key_enc = dk;
+ uint8_t * key_hmac = &dk[32];
+ int rc;
+ HMAC_scrypt_SHA256_CTX hctx;
+ AES_KEY key_enc_exp;
+ struct crypto_aesctr * AES;
+
+ /*
+ * All versions of the scrypt format will start with "scrypt" and
+ * have at least 7 bytes of header.
+ */
+ if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0))
+ return (7);
+
+ /* Check the format. */
+ if (inbuf[6] != 0)
+ return (8);
+
+ /* We must have at least 128 bytes. */
+ if (inbuflen < 128)
+ return (7);
+
+ /* Parse the header and generate derived keys. */
+ if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
+ maxmem, maxmemfrac, maxtime)) != 0)
+ return (rc);
+
+ /* Decrypt data. */
+ if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
+ return (5);
+ if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
+ return (6);
+ crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128);
+ crypto_aesctr_free(AES);
+ *outlen = inbuflen - 128;
+
+ /* Verify signature. */
+ HMAC_scrypt_SHA256_Init(&hctx, key_hmac, 32);
+ HMAC_scrypt_SHA256_Update(&hctx, inbuf, inbuflen - 32);
+ HMAC_scrypt_SHA256_Final(hbuf, &hctx);
+ if (memcmp(hbuf, &inbuf[inbuflen - 32], 32))
+ return (7);
+
+ /* Zero sensitive data. */
+ memset(dk, 0, 64);
+ memset(&key_enc_exp, 0, sizeof(AES_KEY));
+
+ /* Success! */
+ return (0);
+}
+
+/**
+ * scryptenc_file(infile, outfile, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Read a stream from infile and encrypt it, writing the resulting stream to
+ * outfile.
+ */
+int
+scryptenc_file(FILE * infile, FILE * outfile,
+ const uint8_t * passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime)
+{
+ uint8_t buf[ENCBLOCK];
+ uint8_t dk[64];
+ uint8_t hbuf[32];
+ uint8_t header[96];
+ uint8_t * key_enc = dk;
+ uint8_t * key_hmac = &dk[32];
+ size_t readlen;
+ HMAC_scrypt_SHA256_CTX hctx;
+ AES_KEY key_enc_exp;
+ struct crypto_aesctr * AES;
+ int rc;
+
+ /* Generate the header and derived key. */
+ if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
+ maxmem, maxmemfrac, maxtime)) != 0)
+ return (rc);
+
+ /* Hash and write the header. */
+ HMAC_scrypt_SHA256_Init(&hctx, key_hmac, 32);
+ HMAC_scrypt_SHA256_Update(&hctx, header, 96);
+ if (fwrite(header, 96, 1, outfile) != 1)
+ return (12);
+
+ /*
+ * Read blocks of data, encrypt them, and write them out; hash the
+ * data as it is produced.
+ */
+ if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
+ return (5);
+ if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
+ return (6);
+ do {
+ if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0)
+ break;
+ crypto_aesctr_stream(AES, buf, buf, readlen);
+ HMAC_scrypt_SHA256_Update(&hctx, buf, readlen);
+ if (fwrite(buf, 1, readlen, outfile) < readlen)
+ return (12);
+ } while (1);
+ crypto_aesctr_free(AES);
+
+ /* Did we exit the loop due to a read error? */
+ if (ferror(infile))
+ return (13);
+
+ /* Compute the final HMAC and output it. */
+ HMAC_scrypt_SHA256_Final(hbuf, &hctx);
+ if (fwrite(hbuf, 32, 1, outfile) != 1)
+ return (12);
+
+ /* Zero sensitive data. */
+ memset(dk, 0, 64);
+ memset(&key_enc_exp, 0, sizeof(AES_KEY));
+
+ /* Success! */
+ return (0);
+}
+
+/**
+ * scryptdec_file(infile, outfile, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Read a stream from infile and decrypt it, writing the resulting stream to
+ * outfile.
+ */
+int
+scryptdec_file(FILE * infile, FILE * outfile,
+ const uint8_t * passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime)
+{
+ uint8_t buf[ENCBLOCK + 32];
+ uint8_t header[96];
+ uint8_t hbuf[32];
+ uint8_t dk[64];
+ uint8_t * key_enc = dk;
+ uint8_t * key_hmac = &dk[32];
+ size_t buflen = 0;
+ size_t readlen;
+ HMAC_scrypt_SHA256_CTX hctx;
+ AES_KEY key_enc_exp;
+ struct crypto_aesctr * AES;
+ int rc;
+
+ /*
+ * Read the first 7 bytes of the file; all future version of scrypt
+ * are guaranteed to have at least 7 bytes of header.
+ */
+ if (fread(header, 7, 1, infile) < 1) {
+ if (ferror(infile))
+ return (13);
+ else
+ return (7);
+ }
+
+ /* Do we have the right magic? */
+ if (memcmp(header, "scrypt", 6))
+ return (7);
+ if (header[6] != 0)
+ return (8);
+
+ /*
+ * Read another 89 bytes of the file; version 0 of the srypt file
+ * format has a 96-byte header.
+ */
+ if (fread(&header[7], 89, 1, infile) < 1) {
+ if (ferror(infile))
+ return (13);
+ else
+ return (7);
+ }
+
+ /* Parse the header and generate derived keys. */
+ if ((rc = scryptdec_setup(header, dk, passwd, passwdlen,
+ maxmem, maxmemfrac, maxtime)) != 0)
+ return (rc);
+
+ /* Start hashing with the header. */
+ HMAC_scrypt_SHA256_Init(&hctx, key_hmac, 32);
+ HMAC_scrypt_SHA256_Update(&hctx, header, 96);
+
+ /*
+ * We don't know how long the encrypted data block is (we can't know,
+ * since data can be streamed into 'scrypt enc') so we need to read
+ * data and decrypt all of it except the final 32 bytes, then check
+ * if that final 32 bytes is the correct signature.
+ */
+ if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
+ return (5);
+ if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
+ return (6);
+ do {
+ /* Read data until we have more than 32 bytes of it. */
+ if ((readlen = fread(&buf[buflen], 1,
+ ENCBLOCK + 32 - buflen, infile)) == 0)
+ break;
+ buflen += readlen;
+ if (buflen <= 32)
+ continue;
+
+ /*
+ * Decrypt, hash, and output everything except the last 32
+ * bytes out of what we have in our buffer.
+ */
+ HMAC_scrypt_SHA256_Update(&hctx, buf, buflen - 32);
+ crypto_aesctr_stream(AES, buf, buf, buflen - 32);
+ if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32)
+ return (12);
+
+ /* Move the last 32 bytes to the start of the buffer. */
+ memmove(buf, &buf[buflen - 32], 32);
+ buflen = 32;
+ } while (1);
+ crypto_aesctr_free(AES);
+
+ /* Did we exit the loop due to a read error? */
+ if (ferror(infile))
+ return (13);
+
+ /* Did we read enough data that we *might* have a valid signature? */
+ if (buflen < 32)
+ return (7);
+
+ /* Verify signature. */
+ HMAC_scrypt_SHA256_Final(hbuf, &hctx);
+ if (memcmp(hbuf, buf, 32))
+ return (7);
+
+ /* Zero sensitive data. */
+ memset(dk, 0, 64);
+ memset(&key_enc_exp, 0, sizeof(AES_KEY));
+
+ return (0);
+}
diff --git a/scrypt-1.1.6/lib/scryptenc/scryptenc.h b/scrypt-1.1.6/lib/scryptenc/scryptenc.h
new file mode 100644
index 0000000..7dc3dd3
--- /dev/null
+++ b/scrypt-1.1.6/lib/scryptenc/scryptenc.h
@@ -0,0 +1,112 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _SCRYPTENC_H_
+#define _SCRYPTENC_H_
+
+#include <stdint.h>
+#include <stdio.h>
+
+/**
+ * The parameters maxmem, maxmemfrac, and maxtime used by all of these
+ * functions are defined as follows:
+ * maxmem - maximum number of bytes of storage to use for V array (which is
+ * by far the largest consumer of memory). If this value is set to 0, no
+ * maximum will be enforced; any other value less than 1 MiB will be
+ * treated as 1 MiB.
+ * maxmemfrac - maximum fraction of available storage to use for the V array,
+ * where "available storage" is defined as the minimum out of the
+ * RLIMIT_AS, RLIMIT_DATA. and RLIMIT_RSS resource limits (if any are
+ * set). If this value is set to 0 or more than 0.5 it will be treated
+ * as 0.5; and this value will never cause a limit of less than 1 MiB to
+ * be enforced.
+ * maxtime - maximum amount of CPU time to spend computing the derived keys,
+ * in seconds. This limit is only approximately enforced; the CPU
+ * performance is estimated and parameter limits are chosen accordingly.
+ * For the encryption functions, the parameters to the scrypt key derivation
+ * function are chosen to make the key as strong as possible subject to the
+ * specified limits; for the decryption functions, the parameters used are
+ * compared to the computed limits and an error is returned if decrypting
+ * the data would take too much memory or CPU time.
+ */
+/**
+ * Return codes from scrypt(enc|dec)_(buf|file):
+ * 0 success
+ * 1 getrlimit or sysctl(hw.usermem) failed
+ * 2 clock_getres or clock_gettime failed
+ * 3 error computing derived key
+ * 4 could not read salt from /dev/urandom
+ * 5 error in OpenSSL
+ * 6 malloc failed
+ * 7 data is not a valid scrypt-encrypted block
+ * 8 unrecognized scrypt format
+ * 9 decrypting file would take too much memory
+ * 10 decrypting file would take too long
+ * 11 password is incorrect
+ * 12 error writing output file
+ * 13 error reading input file
+ */
+
+/**
+ * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
+ * bytes to outbuf.
+ */
+int scryptenc_buf(const uint8_t *, size_t, uint8_t *,
+ const uint8_t *, size_t, size_t, double, double);
+
+/**
+ * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the
+ * decrypted data length to outlen. The allocated length of outbuf must
+ * be at least inbuflen.
+ */
+int scryptdec_buf(const uint8_t *, size_t, uint8_t *, size_t *,
+ const uint8_t *, size_t, size_t, double, double);
+
+/**
+ * scryptenc_file(infile, outfile, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Read a stream from infile and encrypt it, writing the resulting stream to
+ * outfile.
+ */
+int scryptenc_file(FILE *, FILE *, const uint8_t *, size_t,
+ size_t, double, double);
+
+/**
+ * scryptdec_file(infile, outfile, passwd, passwdlen,
+ * maxmem, maxmemfrac, maxtime):
+ * Read a stream from infile and decrypt it, writing the resulting stream to
+ * outfile.
+ */
+int scryptdec_file(FILE *, FILE *, const uint8_t *, size_t,
+ size_t, double, double);
+
+#endif /* !_SCRYPTENC_H_ */
diff --git a/scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.c b/scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.c
new file mode 100644
index 0000000..14d0d0a
--- /dev/null
+++ b/scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <sys/time.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "crypto_scrypt.h"
+
+#include "scryptenc_cpuperf.h"
+
+#ifdef _WIN32
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+
+static clock_t clocktouse;
+
+static int
+getclockres(double * resd)
+{
+ struct timespec res;
+
+ /*
+ * Try clocks in order of preference until we find one which works.
+ * (We assume that if clock_getres works, clock_gettime will, too.)
+ * The use of if/else/if/else/if/else rather than if/elif/elif/else
+ * is ugly but legal, and allows us to #ifdef things appropriately.
+ */
+#ifdef CLOCK_VIRTUAL
+ if (clock_getres(CLOCK_VIRTUAL, &res) == 0)
+ clocktouse = CLOCK_VIRTUAL;
+ else
+#endif
+#ifdef CLOCK_MONOTONIC
+ if (clock_getres(CLOCK_MONOTONIC, &res) == 0)
+ clocktouse = CLOCK_MONOTONIC;
+ else
+#endif
+ if (clock_getres(CLOCK_REALTIME, &res) == 0)
+ clocktouse = CLOCK_REALTIME;
+ else
+ return (-1);
+
+ /* Convert clock resolution to a double. */
+ *resd = res.tv_sec + res.tv_nsec * 0.000000001;
+
+ return (0);
+}
+
+static int
+getclocktime(struct timespec * ts)
+{
+
+ if (clock_gettime(clocktouse, ts))
+ return (-1);
+
+ return (0);
+}
+
+#else
+static int
+getclockres(double * resd)
+{
+
+ *resd = 1.0 / CLOCKS_PER_SEC;
+
+ return (0);
+}
+
+static int
+getclocktime(struct timespec * ts)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL))
+ return (-1);
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+
+ return (0);
+}
+#endif
+
+static int
+getclockdiff(struct timespec * st, double * diffd)
+{
+ struct timespec en;
+
+ if (getclocktime(&en))
+ return (1);
+ *diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 +
+ (en.tv_sec - st->tv_sec);
+
+ return (0);
+}
+
+/**
+ * scryptenc_cpuperf(opps):
+ * Estimate the number of salsa20/8 cores which can be executed per second,
+ * and return the value via opps.
+ */
+int
+scryptenc_cpuperf(double * opps)
+{
+ struct timespec st;
+ double resd, diffd;
+ uint64_t i = 0;
+
+ /* Get the clock resolution. */
+ if (getclockres(&resd))
+ return (2);
+
+#ifdef DEBUG
+ fprintf(stderr, "Clock resolution is %f\n", resd);
+#endif
+
+ /* Loop until the clock ticks. */
+ if (getclocktime(&st))
+ return (2);
+ do {
+ /* Do an scrypt. */
+ if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0))
+ return (3);
+
+ /* Has the clock ticked? */
+ if (getclockdiff(&st, &diffd))
+ return (2);
+ if (diffd > 0)
+ break;
+ } while (1);
+
+ /* Could how many scryps we can do before the next tick. */
+ if (getclocktime(&st))
+ return (2);
+ do {
+ /* Do an scrypt. */
+ if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0))
+ return (3);
+
+ /* We invoked the salsa20/8 core 512 times. */
+ i += 512;
+
+ /* Check if we have looped for long enough. */
+ if (getclockdiff(&st, &diffd))
+ return (2);
+ if (diffd > resd)
+ break;
+ } while (1);
+
+#ifdef DEBUG
+ fprintf(stderr, "%u salsa20/8 cores performed in %f seconds\n",
+ (uintmax_t)i, diffd);
+#endif
+
+ /* We can do approximately i salsa20/8 cores per diffd seconds. */
+ *opps = i / diffd;
+ return (0);
+}
diff --git a/scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.h b/scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.h
new file mode 100644
index 0000000..e236fff
--- /dev/null
+++ b/scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _SCRYPTENC_CPUPERF_H_
+#define _SCRYPTENC_CPUPERF_H_
+
+/**
+ * scryptenc_cpuperf(opps):
+ * Estimate the number of salsa20/8 cores which can be executed per second,
+ * and return the value via opps.
+ */
+int scryptenc_cpuperf(double *);
+
+#endif /* !_SCRYPTENC_CPUPERF_H_ */
diff --git a/scrypt-1.1.6/lib/util/memlimit.c b/scrypt-1.1.6/lib/util/memlimit.c
new file mode 100644
index 0000000..6268163
--- /dev/null
+++ b/scrypt-1.1.6/lib/util/memlimit.c
@@ -0,0 +1,343 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <sys/types.h>
+
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0502
+#include <Windows.h>
+#include <tchar.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYSCTL_HW_USERMEM
+#include <sys/sysctl.h>
+#endif
+#ifdef HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#include "memlimit.h"
+
+#ifdef HAVE_SYSCTL_HW_USERMEM
+static int
+memlimit_sysctl_hw_usermem(size_t * memlimit)
+{
+ int mib[2];
+ uint8_t usermembuf[8];
+ size_t usermemlen = 8;
+ uint64_t usermem;
+
+ /* Ask the kernel how much RAM we have. */
+ mib[0] = CTL_HW;
+ mib[1] = HW_USERMEM;
+ if (sysctl(mib, 2, usermembuf, &usermemlen, NULL, 0))
+ return (1);
+
+ /*
+ * Parse as either a uint64_t or a uint32_t based on the length of
+ * output the kernel reports having copied out. It appears that all
+ * systems providing a sysctl interface for reading integers copy
+ * them out as system-endian values, so we don't need to worry about
+ * parsing them.
+ */
+ if (usermemlen == sizeof(uint64_t))
+ usermem = *(uint64_t *)usermembuf;
+ else if (usermemlen == sizeof(uint32_t))
+ usermem = *(uint32_t *)usermembuf;
+ else
+ return (1);
+
+ /* Return the sysctl value, but clamp to SIZE_MAX if necessary. */
+#if UINT64_MAX > SIZE_MAX
+ if (usermem > SIZE_MAX)
+ *memlimit = SIZE_MAX;
+ else
+ *memlimit = usermem;
+#else
+ *memlimit = usermem;
+#endif
+
+ /* Success! */
+ return (0);
+}
+#endif
+
+/* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */
+#ifndef HAVE_STRUCT_SYSINFO
+#undef HAVE_SYSINFO
+#endif
+
+/* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */
+#ifndef HAVE_STRUCT_SYSINFO_TOTALRAM
+#undef HAVE_SYSINFO
+#endif
+
+#ifdef HAVE_SYSINFO
+static int
+memlimit_sysinfo(size_t * memlimit)
+{
+ struct sysinfo info;
+ uint64_t totalmem;
+
+ /* Get information from the kernel. */
+ if (sysinfo(&info))
+ return (1);
+ totalmem = info.totalram;
+
+ /* If we're on a modern kernel, adjust based on mem_unit. */
+#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT
+ totalmem = totalmem * info.mem_unit;
+#endif
+
+ /* Return the value, but clamp to SIZE_MAX if necessary. */
+#if UINT64_MAX > SIZE_MAX
+ if (totalmem > SIZE_MAX)
+ *memlimit = SIZE_MAX;
+ else
+ *memlimit = totalmem;
+#else
+ *memlimit = totalmem;
+#endif
+
+ /* Success! */
+ return (0);
+}
+#endif /* HAVE_SYSINFO */
+
+#ifndef _WIN32
+static int
+memlimit_rlimit(size_t * memlimit)
+{
+ struct rlimit rl;
+ uint64_t memrlimit;
+
+ /* Find the least of... */
+ memrlimit = (uint64_t)(-1);
+
+ /* ... RLIMIT_AS... */
+#ifdef RLIMIT_AS
+ if (getrlimit(RLIMIT_AS, &rl))
+ return (1);
+ if ((rl.rlim_cur != RLIM_INFINITY) &&
+ ((uint64_t)rl.rlim_cur < memrlimit))
+ memrlimit = rl.rlim_cur;
+#endif
+
+ /* ... RLIMIT_DATA... */
+ if (getrlimit(RLIMIT_DATA, &rl))
+ return (1);
+ if ((rl.rlim_cur != RLIM_INFINITY) &&
+ ((uint64_t)rl.rlim_cur < memrlimit))
+ memrlimit = rl.rlim_cur;
+
+ /* ... and RLIMIT_RSS. */
+#ifdef RLIMIT_RSS
+ if (getrlimit(RLIMIT_RSS, &rl))
+ return (1);
+ if ((rl.rlim_cur != RLIM_INFINITY) &&
+ ((uint64_t)rl.rlim_cur < memrlimit))
+ memrlimit = rl.rlim_cur;
+#endif
+
+ /* Return the value, but clamp to SIZE_MAX if necessary. */
+#if UINT64_MAX > SIZE_MAX
+ if (memrlimit > SIZE_MAX)
+ *memlimit = SIZE_MAX;
+ else
+ *memlimit = memrlimit;
+#else
+ *memlimit = memrlimit;
+#endif
+
+ /* Success! */
+ return (0);
+}
+#endif
+
+#ifdef _SC_PHYS_PAGES
+
+/* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */
+#ifndef _SC_PAGE_SIZE
+#define _SC_PAGE_SIZE _SC_PAGESIZE
+#endif
+
+static int
+memlimit_sysconf(size_t * memlimit)
+{
+ long pagesize;
+ long physpages;
+ uint64_t totalmem;
+
+ /* Set errno to 0 in order to distinguish "no limit" from "error". */
+ errno = 0;
+
+ /* Read the two limits. */
+ if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) ||
+ ((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) {
+ /* Did an error occur? */
+ if (errno != 0)
+ return (1);
+
+ /* If not, there is no limit. */
+ totalmem = (uint64_t)(-1);
+ } else {
+ /* Compute the limit. */
+ totalmem = (uint64_t)(pagesize) * (uint64_t)(physpages);
+ }
+
+ /* Return the value, but clamp to SIZE_MAX if necessary. */
+#if UINT64_MAX > SIZE_MAX
+ if (totalmem > SIZE_MAX)
+ *memlimit = SIZE_MAX;
+ else
+ *memlimit = totalmem;
+#else
+ *memlimit = totalmem;
+#endif
+
+ /* Success! */
+ return (0);
+}
+#endif
+
+#ifdef _WIN32
+static int
+memlimit_windows(size_t * memlimit)
+{
+ MEMORYSTATUSEX state;
+ state.dwLength = sizeof(state);
+
+ if(!GlobalMemoryStatusEx (&state))
+ return (1);
+
+
+ *memlimit = state.ullTotalPhys;
+ return (0);
+
+}
+#endif
+
+int
+memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit)
+{
+ size_t sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit;
+ size_t sysconf_memlimit;
+ size_t memlimit_min;
+ size_t memavail;
+ size_t windows_memlimit;
+
+ /* Get memory limits. */
+#ifdef HAVE_SYSCTL_HW_USERMEM
+ if (memlimit_sysctl_hw_usermem(&sysctl_memlimit))
+ return (1);
+#else
+ sysctl_memlimit = (size_t)(-1);
+#endif
+#ifdef HAVE_SYSINFO
+ if (memlimit_sysinfo(&sysinfo_memlimit))
+ return (1);
+#else
+ sysinfo_memlimit = (size_t)(-1);
+#endif
+#ifndef _WIN32
+ if (memlimit_rlimit(&rlimit_memlimit))
+ return (1);
+#else
+ rlimit_memlimit=(size_t)(-1);
+#endif
+#ifdef _SC_PHYS_PAGES
+ if (memlimit_sysconf(&sysconf_memlimit))
+ return (1);
+#else
+ sysconf_memlimit = (size_t)(-1);
+#endif
+#ifdef _WIN32
+ if (memlimit_windows(&windows_memlimit))
+ return (1);
+#else
+ windows_memlimit=(size_t)(-1);
+#endif
+
+#ifdef DEBUG
+ fprintf(stderr, "Memory limits are %u %u %u %u %u\n",
+ sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit,
+ sysconf_memlimit, windows_memlimit);
+#endif
+
+ /* Find the smallest of them. */
+ memlimit_min = (size_t)(-1);
+ if (memlimit_min > sysctl_memlimit)
+ memlimit_min = sysctl_memlimit;
+ if (memlimit_min > sysinfo_memlimit)
+ memlimit_min = sysinfo_memlimit;
+ if (memlimit_min > rlimit_memlimit)
+ memlimit_min = rlimit_memlimit;
+ if (memlimit_min > sysconf_memlimit)
+ memlimit_min = sysconf_memlimit;
+ if (memlimit_min > windows_memlimit)
+ memlimit_min = windows_memlimit;
+
+ /* Only use the specified fraction of the available memory. */
+ if ((maxmemfrac > 0.5) || (maxmemfrac == 0.0))
+ maxmemfrac = 0.5;
+ memavail = maxmemfrac * memlimit_min;
+
+ /* Don't use more than the specified maximum. */
+ if ((maxmem > 0) && (memavail > maxmem))
+ memavail = maxmem;
+
+ /* But always allow at least 1 MiB. */
+ if (memavail < 1048576)
+ memavail = 1048576;
+
+#ifdef DEBUG
+ fprintf(stderr, "Allowing up to %u memory to be used\n", memavail);
+#endif
+
+ /* Return limit via the provided pointer. */
+ *memlimit = memavail;
+ return (0);
+}
diff --git a/scrypt-1.1.6/lib/util/memlimit.h b/scrypt-1.1.6/lib/util/memlimit.h
new file mode 100644
index 0000000..d3b4891
--- /dev/null
+++ b/scrypt-1.1.6/lib/util/memlimit.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _MEMLIMIT_H_
+#define _MEMLIMIT_H_
+
+#include <stddef.h>
+
+/**
+ * memtouse(maxmem, maxmemfrac, memlimit):
+ * Examine the system and return via memlimit the amount of RAM which should
+ * be used -- the specified fraction of the available RAM, but no more than
+ * maxmem, and no less than 1MiB.
+ */
+int memtouse(size_t, double, size_t *);
+
+#endif /* !_MEMLIMIT_H_ */
diff --git a/scrypt-1.1.6/lib/util/readpass.h b/scrypt-1.1.6/lib/util/readpass.h
new file mode 100644
index 0000000..da57278
--- /dev/null
+++ b/scrypt-1.1.6/lib/util/readpass.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _READPASS_H_
+#define _READPASS_H_
+
+/**
+ * tarsnap_getpass(passwd, prompt, confirmprompt, devtty)
+ * If ${devtty} is non-zero, read a password from /dev/tty if possible; if
+ * not, read from stdin. If reading from a tty (either /dev/tty or stdin),
+ * disable echo and prompt the user by printing ${prompt} to stderr. If
+ * ${confirmprompt} is non-NULL, read a second password (prompting if a
+ * terminal is being used) and repeat until the user enters the same password
+ * twice. Return the password as a malloced NUL-terminated string via
+ * ${passwd}. The obscure name is to avoid namespace collisions due to the
+ * getpass / readpass / readpassphrase / etc. functions in various libraries.
+ */
+int tarsnap_readpass(char **, const char *, const char *, int);
+
+#endif /* !_READPASS_H_ */
diff --git a/scrypt-1.1.6/lib/util/sysendian.h b/scrypt-1.1.6/lib/util/sysendian.h
new file mode 100644
index 0000000..62ef31a
--- /dev/null
+++ b/scrypt-1.1.6/lib/util/sysendian.h
@@ -0,0 +1,140 @@
+/*-
+ * Copyright 2007-2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _SYSENDIAN_H_
+#define _SYSENDIAN_H_
+
+#include "scrypt_platform.h"
+
+/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */
+#if !HAVE_DECL_BE64ENC
+#undef HAVE_SYS_ENDIAN_H
+#endif
+
+#ifdef HAVE_SYS_ENDIAN_H
+
+#include <sys/endian.h>
+
+#else
+
+#include <stdint.h>
+
+static inline uint32_t
+be32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
+ ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
+}
+
+static inline void
+be32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[3] = x & 0xff;
+ p[2] = (x >> 8) & 0xff;
+ p[1] = (x >> 16) & 0xff;
+ p[0] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+be64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
+ ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
+ ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
+ ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
+}
+
+static inline void
+be64enc(void *pp, uint64_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[7] = x & 0xff;
+ p[6] = (x >> 8) & 0xff;
+ p[5] = (x >> 16) & 0xff;
+ p[4] = (x >> 24) & 0xff;
+ p[3] = (x >> 32) & 0xff;
+ p[2] = (x >> 40) & 0xff;
+ p[1] = (x >> 48) & 0xff;
+ p[0] = (x >> 56) & 0xff;
+}
+
+static inline uint32_t
+le32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
+ ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
+}
+
+static inline void
+le32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+ p[2] = (x >> 16) & 0xff;
+ p[3] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+le64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
+ ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
+ ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
+ ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
+}
+
+static inline void
+le64enc(void *pp, uint64_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+ p[2] = (x >> 16) & 0xff;
+ p[3] = (x >> 24) & 0xff;
+ p[4] = (x >> 32) & 0xff;
+ p[5] = (x >> 40) & 0xff;
+ p[6] = (x >> 48) & 0xff;
+ p[7] = (x >> 56) & 0xff;
+}
+#endif /* !HAVE_SYS_ENDIAN_H */
+
+#endif /* !_SYSENDIAN_H_ */
diff --git a/scrypt-1.1.6/lib/util/warn.c b/scrypt-1.1.6/lib/util/warn.c
new file mode 100644
index 0000000..504f935
--- /dev/null
+++ b/scrypt-1.1.6/lib/util/warn.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#ifdef HAVE_ERR_H
+/*
+ * Everything is provided through err.h and the associated library, so we
+ * don't need to do anything here.
+ */
+#else
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "warn.h"
+
+const char * warn_progname = "(null)";
+
+void
+warn(const char * fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s", warn_progname);
+ if (fmt != NULL) {
+ fprintf(stderr, ": ");
+ vfprintf(stderr, fmt, ap);
+ }
+ fprintf(stderr, ": %s\n", strerror(errno));
+ va_end(ap);
+}
+
+void
+warnx(const char * fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s", warn_progname);
+ if (fmt != NULL) {
+ fprintf(stderr, ": ");
+ vfprintf(stderr, fmt, ap);
+ }
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+#endif
diff --git a/scrypt-1.1.6/lib/util/warn.h b/scrypt-1.1.6/lib/util/warn.h
new file mode 100644
index 0000000..262d24b
--- /dev/null
+++ b/scrypt-1.1.6/lib/util/warn.h
@@ -0,0 +1,13 @@
+#ifndef _WARN_H_
+#define _WARN_H_
+
+#ifdef HAVE_ERR_H
+#include <err.h>
+#else
+#define NEED_WARN_PROGNAME
+const char * warn_progname;
+void warn(const char *, ...);
+void warnx(const char *, ...);
+#endif
+
+#endif /* !_WARN_H_ */
diff --git a/scrypt-1.1.6/scrypt_platform.h b/scrypt-1.1.6/scrypt_platform.h
new file mode 100644
index 0000000..5cec236
--- /dev/null
+++ b/scrypt-1.1.6/scrypt_platform.h
@@ -0,0 +1,12 @@
+#ifndef _SCRYPT_PLATFORM_H_
+#define _SCRYPT_PLATFORM_H_
+
+#if defined(CONFIG_H_FILE)
+#include CONFIG_H_FILE
+#elif defined(HAVE_CONFIG_H)
+#include "config.h"
+#else
+#error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined.
+#endif
+
+#endif /* !_SCRYPT_PLATFORM_H_ */
diff --git a/scrypt.py b/scrypt.py
new file mode 100644
index 0000000..d504400
--- /dev/null
+++ b/scrypt.py
@@ -0,0 +1,224 @@
+import imp
+import os
+import sys
+
+from ctypes import (cdll,
+ POINTER, pointer,
+ c_char_p,
+ c_size_t, c_double, c_int, c_uint64, c_uint32,
+ create_string_buffer)
+
+_scrypt = cdll.LoadLibrary(imp.find_module('_scrypt')[1])
+
+_scryptenc_buf = _scrypt.exp_scryptenc_buf
+_scryptenc_buf.argtypes = [c_char_p, # const uint_t *inbuf
+ c_size_t, # size_t inbuflen
+ c_char_p, # uint8_t *outbuf
+ c_char_p, # const uint8_t *passwd
+ c_size_t, # size_t passwdlen
+ c_size_t, # size_t maxmem
+ c_double, # double maxmemfrac
+ c_double, # double maxtime
+ ]
+_scryptenc_buf.restype = c_int
+
+_scryptdec_buf = _scrypt.exp_scryptdec_buf
+_scryptdec_buf.argtypes = [c_char_p, # const uint8_t *inbuf
+ c_size_t, # size_t inbuflen
+ c_char_p, # uint8_t *outbuf
+ POINTER(c_size_t), # size_t *outlen
+ c_char_p, # const uint8_t *passwd
+ c_size_t, # size_t passwdlen
+ c_size_t, # size_t maxmem
+ c_double, # double maxmemfrac
+ c_double, # double maxtime
+ ]
+_scryptdec_buf.restype = c_int
+
+_crypto_scrypt = _scrypt.exp_crypto_scrypt
+_crypto_scrypt.argtypes = [c_char_p, # const uint8_t *passwd
+ c_size_t, # size_t passwdlen
+ c_char_p, # const uint8_t *salt
+ c_size_t, # size_t saltlen
+ c_uint64, # uint64_t N
+ c_uint32, # uint32_t r
+ c_uint32, # uint32_t p
+ c_char_p, # uint8_t *buf
+ c_size_t, # size_t buflen
+ ]
+_crypto_scrypt.restype = c_int
+
+ERROR_MESSAGES = ['success',
+ 'getrlimit or sysctl(hw.usermem) failed',
+ 'clock_getres or clock_gettime failed',
+ 'error computing derived key',
+ 'could not read salt from /dev/urandom',
+ 'error in OpenSSL',
+ 'malloc failed',
+ 'data is not a valid scrypt-encrypted block',
+ 'unrecognized scrypt format',
+ 'decrypting file would take too much memory',
+ 'decrypting file would take too long',
+ 'password is incorrect',
+ 'error writing output file',
+ 'error reading input file']
+
+MAXMEM_DEFAULT = 0
+MAXMEMFRAC_DEFAULT = 0.5
+MAXTIME_DEFAULT = 300.0
+MAXTIME_DEFAULT_ENC = 5.0
+
+IS_PY2 = sys.version_info < (3, 0, 0, 'final', 0)
+
+
+class error(Exception):
+ def __init__(self, scrypt_code):
+ if isinstance(scrypt_code, int):
+ self._scrypt_code = scrypt_code
+ super(error, self).__init__(ERROR_MESSAGES[scrypt_code])
+ else:
+ self._scrypt_code = -1
+ super(error, self).__init__(scrypt_code)
+
+
+def _ensure_bytes(data):
+ if IS_PY2 and isinstance(data, unicode):
+ raise TypeError('can not encrypt/decrypt unicode objects')
+
+ if not IS_PY2 and isinstance(data, str):
+ return bytes(data, 'utf-8')
+
+ return data
+
+
+def encrypt(input, password,
+ maxtime=MAXTIME_DEFAULT_ENC,
+ maxmem=MAXMEM_DEFAULT,
+ maxmemfrac=MAXMEMFRAC_DEFAULT):
+ """
+ Encrypt a string using a password. The resulting data will have len =
+ len(input) + 128.
+
+ Notes for Python 2:
+ - `input` and `password` must be str instances
+ - The result will be a str instance
+
+ Notes for Python 3:
+ - `input` and `password` can be both str and bytes. If they are str
+ instances, they will be encoded with utf-8
+ - The result will be a bytes instance
+
+ Exceptions raised:
+ - TypeError on invalid input
+ - scrypt.error if encryption failed
+
+ For more information on the `maxtime`, `maxmem`, and `maxmemfrac`
+ parameters, see the scrypt documentation.
+ """
+
+ input = _ensure_bytes(input)
+ password = _ensure_bytes(password)
+
+ outbuf = create_string_buffer(len(input) + 128)
+ result = _scryptenc_buf(input, len(input),
+ outbuf,
+ password, len(password),
+ maxmem, maxmemfrac, maxtime)
+ if result:
+ raise error(result)
+
+ return outbuf.raw
+
+
+def decrypt(input, password,
+ maxtime=MAXTIME_DEFAULT,
+ maxmem=MAXMEM_DEFAULT,
+ maxmemfrac=MAXMEMFRAC_DEFAULT,
+ encoding='utf-8'):
+ """
+ Decrypt a string using a password.
+
+ Notes for Python 2:
+ - `input` and `password` must be str instances
+ - The result will be a str instance
+ - The encoding parameter is ignored
+
+ Notes for Python 3:
+ - `input` and `password` can be both str and bytes. If they are str
+ instances, they wil be encoded with utf-8. `input` *should*
+ really be a bytes instance, since that's what `encrypt` returns.
+ - The result will be a str instance encoded with `encoding`.
+ If encoding=None, the result will be a bytes instance.
+
+ Exceptions raised:
+ - TypeError on invalid input
+ - scrypt.error if decryption failed
+
+ For more information on the `maxtime`, `maxmem`, and `maxmemfrac`
+ parameters, see the scrypt documentation.
+ """
+
+ outbuf = create_string_buffer(len(input))
+ outbuflen = pointer(c_size_t(0))
+
+ input = _ensure_bytes(input)
+ password = _ensure_bytes(password)
+
+ result = _scryptdec_buf(input, len(input),
+ outbuf, outbuflen,
+ password, len(password),
+ maxmem, maxmemfrac, maxtime)
+
+ if result:
+ raise error(result)
+
+ out_bytes = outbuf.raw[:outbuflen.contents.value]
+
+ if IS_PY2 or encoding is None:
+ return out_bytes
+
+ return str(out_bytes, encoding)
+
+
+def hash(password, salt, N=1 << 14, r=8, p=1, buflen=64):
+ """
+ Compute scrypt(password, salt, N, r, p, buflen).
+
+ The parameters r, p, and buflen must satisfy r * p < 2^30 and
+ buflen <= (2^32 - 1) * 32. The parameter N must be a power of 2
+ greater than 1. N, r and p must all be positive.
+
+ Notes for Python 2:
+ - `password` and `salt` must be str instances
+ - The result will be a str instance
+
+ Notes for Python 3:
+ - `password` and `salt` can be both str and bytes. If they are str
+ instances, they wil be encoded with utf-8.
+ - The result will be a bytes instance
+
+ Exceptions raised:
+ - TypeError on invalid input
+ - scrypt.error if scrypt failed
+ """
+
+ outbuf = create_string_buffer(buflen)
+
+ password = _ensure_bytes(password)
+ salt = _ensure_bytes(salt)
+
+ if r * p >= (1 << 30) or N <= 1 or (N & (N - 1)) != 0 or p < 1 or r < 1:
+ raise error('hash parameters are wrong (r*p should be < 2**30, and N should be a power of two > 1)')
+
+ result = _crypto_scrypt(password, len(password),
+ salt, len(salt),
+ N, r, p,
+ outbuf, buflen)
+
+ if result:
+ raise error('could not compute hash')
+
+ return outbuf.raw
+
+
+__all__ = ['error', 'encrypt', 'decrypt', 'hash']
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..0190808
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+from distutils.core import setup, Extension, Command
+
+import sys
+import platform
+
+includes = []
+library_dirs = []
+cmdclasses = dict()
+CFLAGS = []
+
+
+class Tester(Command):
+ """Runs unit tests"""
+
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ if ((sys.version_info > (3, 2, 0, 'final', 0)) or
+ (sys.version_info > (2, 7, 0, 'final', 0) and sys.version_info < (3, 0, 0, 'final', 0))):
+ from unittest import TextTestRunner, defaultTestLoader
+ else:
+ try:
+ from unittest2 import TextTestRunner, defaultTestLoader
+ except ImportError:
+ print("Please install unittest2 to run the test suite")
+ exit(-1)
+ from tests import test_scrypt, test_scrypt_py2x, test_scrypt_py3x
+ suite = defaultTestLoader.loadTestsFromModule(test_scrypt)
+ suite.addTests(defaultTestLoader.loadTestsFromModule(test_scrypt_py2x))
+ suite.addTests(defaultTestLoader.loadTestsFromModule(test_scrypt_py3x))
+ runner = TextTestRunner()
+ result = runner.run(suite)
+
+cmdclasses['test'] = Tester
+
+if sys.platform.startswith('linux'):
+ define_macros = [('HAVE_CLOCK_GETTIME', '1'),
+ ('HAVE_LIBRT', '1'),
+ ('HAVE_POSIX_MEMALIGN', '1'),
+ ('HAVE_STRUCT_SYSINFO', '1'),
+ ('HAVE_STRUCT_SYSINFO_MEM_UNIT', '1'),
+ ('HAVE_STRUCT_SYSINFO_TOTALRAM', '1'),
+ ('HAVE_SYSINFO', '1'),
+ ('HAVE_SYS_SYSINFO_H', '1'),
+ ('_FILE_OFFSET_BITS', '64')]
+ libraries = ['crypto', 'rt']
+ CFLAGS.append('-O2')
+elif sys.platform.startswith('win32'):
+ define_macros = []
+ library_dirs = ['c:\OpenSSL-Win32\lib\MinGW']
+ libraries = ['eay32']
+ includes = ['c:\OpenSSL-Win32\include']
+elif sys.platform.startswith('darwin') and platform.mac_ver()[0] < '10.6':
+ define_macros = [('HAVE_SYSCTL_HW_USERMEM', '1')]
+ libraries = ['crypto']
+else:
+ define_macros = [('HAVE_POSIX_MEMALIGN', '1'),
+ ('HAVE_SYSCTL_HW_USERMEM', '1')]
+ libraries = ['crypto']
+
+scrypt_module = Extension('_scrypt',
+ sources=['src/scrypt.c',
+ 'scrypt-1.1.6/lib/crypto/crypto_aesctr.c',
+ 'scrypt-1.1.6/lib/crypto/crypto_scrypt-nosse.c',
+ 'scrypt-1.1.6/lib/crypto/sha256.c',
+ 'scrypt-1.1.6/lib/scryptenc/scryptenc.c',
+ 'scrypt-1.1.6/lib/scryptenc/scryptenc_cpuperf.c',
+ 'scrypt-1.1.6/lib/util/memlimit.c',
+ 'scrypt-1.1.6/lib/util/warn.c'],
+ include_dirs=['scrypt-1.1.6',
+ 'scrypt-1.1.6/lib',
+ 'scrypt-1.1.6/lib/scryptenc',
+ 'scrypt-1.1.6/lib/crypto',
+ 'scrypt-1.1.6/lib/util'] + includes,
+ define_macros=[('HAVE_CONFIG_H', None)] + define_macros,
+ extra_compile_args=CFLAGS,
+ library_dirs=library_dirs,
+ libraries=libraries)
+
+setup(name='scrypt',
+ version='0.6.1',
+ description='Bindings for the scrypt key derivation function library',
+ author='Magnus Hallin',
+ author_email='mhallin@gmail.com',
+ url='http://bitbucket.org/mhallin/py-scrypt',
+ py_modules=['scrypt'],
+ ext_modules=[scrypt_module],
+ classifiers=['Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Security :: Cryptography',
+ 'Topic :: Software Development :: Libraries'],
+ license='2-clause BSD',
+ long_description=open('README.rst').read(),
+ cmdclass=cmdclasses)
diff --git a/src/scrypt.c b/src/scrypt.c
new file mode 100644
index 0000000..69d6816
--- /dev/null
+++ b/src/scrypt.c
@@ -0,0 +1,74 @@
+/*-
+ * Copyright 2010 Magnus Hallin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <Python.h>
+
+#include "scryptenc.h"
+#include "crypto_scrypt.h"
+
+#if !defined(DL_EXPORT)
+
+#if defined(HAVE_DECLSPEC_DLL)
+#define DL_EXPORT(type) __declspec(dllexport) type
+#else
+#define DL_EXPORT(type) type
+#endif
+
+#endif
+
+
+/* Exported trampolines */
+DL_EXPORT(int) exp_scryptenc_buf(const uint8_t *inbuf, size_t inbuflen,
+ uint8_t *outbuf,
+ const uint8_t *passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime) {
+ return scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
+ maxmem, maxmemfrac, maxtime);
+}
+
+DL_EXPORT(int) exp_scryptdec_buf(const uint8_t *inbuf, size_t inbuflen,
+ uint8_t *outbuf, size_t *outbuflen,
+ const uint8_t *passwd, size_t passwdlen,
+ size_t maxmem, double maxmemfrac, double maxtime) {
+ return scryptdec_buf(inbuf, inbuflen, outbuf, outbuflen, passwd, passwdlen,
+ maxmem, maxmemfrac, maxtime);
+}
+
+DL_EXPORT(int) exp_crypto_scrypt(const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *salt, size_t saltlen,
+ uint64_t N, uint32_t r, uint32_t p,
+ uint8_t *buf, size_t buflen) {
+ return crypto_scrypt(passwd, passwdlen, salt, saltlen,
+ N, r, p, buf, buflen);
+}
+
+/*
+ We need a stub init_scrypt function so the module will link as a proper module.
+
+ Do not import _scrypt from python; it will not work since _scrypt is not a *real* module
+*/
+PyMODINIT_FUNC init_scrypt(void) { }
+PyMODINIT_FUNC PyInit__scrypt(void) { }
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/ciphertexts.csv b/tests/ciphertexts.csv
new file mode 100644
index 0000000..7594dd4
--- /dev/null
+++ b/tests/ciphertexts.csv
@@ -0,0 +1,6 @@
+input,password,maxtime,maxmem,maxmemfrac,ciphertext
+message,password,0.01,0,0.0625,736372797074000a00000008000000019f6d3fe5e9423a12d330e35089befdfbb476c7d4faea91492a2561f942c1599701aba424220218b9f81812df06d7cf2a281fd0fdbc7c9d978c335bf5209b1062ee2e49993c4d3a37d347ad6bf0eaecc2fe579a6f320b0acf475882c222c0ba34a7ac5379bedc82358bb3f736ea31d4b824e8bc95c75579
+message,password,5.0000,0.0000,0.1250,736372797074000a00000008000000cb974d55992fea307caa3593205c8851cd56b3ddfd241ee7b1c075cfd2e2f871dddcee71b6bc2b6b075caa1699ea58ce32e9fcd802b18069828201692380574e23e84c2d39d6a951c9c2401dea1a0fa44195b01fca9332f7aac223c84251c69a28037788e09cf297a003a62e2e7c5b6f039e3c1d21fa5da6
+message,password,0.5000,0.0000,0.0625,736372797074000a00000008000000141429bb22aef840e1dde29564dada8f2a77fc2855fe8c9e27e5bf5df4a0eec330344e8471bf83e2466a28acc9d1813a3e50e64697fb8e9c7c17954950f16a5b78fe114d8b147c5936802fe52b17f83e6da9de884257f2a938aa37c2e92b1c33cd9afd0f5e91baba29be4b1c0709bd2a31a4c52394f9b0d4
+message,password,0.5000,0.0000,0.1250,736372797074000a0000000800000014e9baa49b57b2e5b561df54121d870532714f063f295c15ca48e32b677e8e11126ab8da24683951749a19eede36ea3768cb01e8eda6c0f570db7051e07e99d2d687ce28f96aa2e6afa8a0a8c5d902c847e041e14435a22d873c4e676f7a7f5ab9107171b583d02724c056707640931a3c160b9e0ef87bae
+message,password,0.5000,10485760.0000,0.1250,736372797074000a0000000800000014e53c55cd89b6e2de639c1621d92e79212e5f4fc793387435486427eb8adeb192382b5b6397f98ac66fa528a13cba01bd611082369fe1e2244a01ba8329ff6fcaa2db5e87fb75683ae6fc636d873c2e004a0209b947c7b8e805174d65ec0ac2cb597baadae6cf092c33a5096590860b51570faa89e39bf0 \ No newline at end of file
diff --git a/tests/hashvectors.csv b/tests/hashvectors.csv
new file mode 100644
index 0000000..bcf6b40
--- /dev/null
+++ b/tests/hashvectors.csv
@@ -0,0 +1,5 @@
+password,salt,n,r,p,hexhash
+,,16,1,1,77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906
+password,NaCl,1024,8,16,fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
+pleaseletmein,SodiumChloride,16384,8,1,7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887
+pleaseletmein,SodiumChloride,32768,16,4,cbc397a9b5f5a53048c5b9f039ee1246d9532c8089fb346a4ab47cd0701febf18652b1ee042e070d1b6c631c43fd05ececd5b165ee1c2ffc1a2e98406fc2cd52 \ No newline at end of file
diff --git a/tests/test_scrypt.py b/tests/test_scrypt.py
new file mode 100644
index 0000000..4c5a207
--- /dev/null
+++ b/tests/test_scrypt.py
@@ -0,0 +1,285 @@
+# -*- coding: utf-8 -*-
+
+from os import urandom
+from os.path import dirname, abspath, sep
+from sys import version_info
+from csv import reader
+from binascii import a2b_hex, b2a_hex
+import base64
+import json
+
+if ((version_info > (3, 2, 0, 'final', 0)) or
+ (version_info > (2, 7, 0, 'final', 0) and version_info < (3, 0, 0, 'final', 0))):
+ import unittest as testm
+else:
+ try:
+ import unittest2 as testm
+ except ImportError:
+ print("Please install unittest2 to run the test suite")
+ exit(-1)
+
+import scrypt
+
+
+class TestScrypt(testm.TestCase):
+
+ def setUp(self):
+ self.input = "message"
+ self.password = "password"
+ self.longinput = str(urandom(100000))
+ self.five_minutes = 300.0
+ self.five_seconds = 5.0
+ self.one_byte = 1 # in Bytes
+ self.one_megabyte = 1024 * 1024 # in Bytes
+ self.ten_megabytes = 10 * self.one_megabyte
+ base_dir = dirname(abspath(__file__)) + sep
+ cvf = open(base_dir + "ciphertexts.csv", "r")
+ ciphertxt_reader = reader(cvf, dialect="excel")
+ self.ciphertexts = []
+ for row in ciphertxt_reader:
+ self.ciphertexts.append(row)
+ cvf.close()
+ self.ciphertext = a2b_hex(bytes(self.ciphertexts[1][5].encode('ascii')))
+
+ def test_encrypt_decrypt(self):
+ """Test encrypt for simple encryption and decryption"""
+ s = scrypt.encrypt(self.input, self.password, 0.1)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt(self):
+ """Test encrypt takes input and password strings as
+ positional arguments and produces ciphertext"""
+ s = scrypt.encrypt(self.input, self.password)
+ self.assertEqual(len(s), 128 + len(self.input))
+
+ def test_encrypt_input_and_password_as_keywords(self):
+ """Test encrypt for input and password accepted as keywords"""
+ s = scrypt.encrypt(password=self.password, input=self.input)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_missing_input_keyword_argument(self):
+ """Test encrypt raises TypeError if keyword argument missing input"""
+ self.assertRaises(TypeError, lambda: scrypt.encrypt(password=self.password))
+
+ def test_encrypt_missing_password_positional_argument(self):
+ """Test encrypt raises TypeError if second positional argument missing
+ (password)"""
+ self.assertRaises(TypeError, lambda: scrypt.encrypt(self.input))
+
+ def test_encrypt_missing_both_required_positional_arguments(self):
+ """Test encrypt raises TypeError if both positional arguments missing
+ (input and password)"""
+ self.assertRaises(TypeError, lambda: scrypt.encrypt())
+
+ def test_encrypt_maxtime_positional(self):
+ """Test encrypt maxtime accepts maxtime at position 3"""
+ s = scrypt.encrypt(self.input, self.password, 0.01)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxtime_key(self):
+ """Test encrypt maxtime accepts maxtime as keyword argument"""
+ s = scrypt.encrypt(self.input, self.password, maxtime=0.01)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxmem_positional(self):
+ """Test encrypt maxmem accepts 4th positional argument and exactly
+ (1 megabyte) of storage to use for V array"""
+ s = scrypt.encrypt(self.input, self.password, 0.01, self.one_megabyte)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxmem_undersized(self):
+ """Test encrypt maxmem accepts (< 1 megabyte) of storage to use for V array"""
+ s = scrypt.encrypt(self.input, self.password, 0.01, self.one_byte)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxmem_in_normal_range(self):
+ """Test encrypt maxmem accepts (> 1 megabyte) of storage to use for V array"""
+ s = scrypt.encrypt(self.input,
+ self.password,
+ 0.01,
+ self.ten_megabytes)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxmem_keyword_argument(self):
+ """Test encrypt maxmem accepts exactly (1 megabyte) of storage to use for
+ V array"""
+ s = scrypt.encrypt(self.input,
+ self.password,
+ maxmem=self.one_megabyte,
+ maxtime=0.01)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxmemfrac_positional(self):
+ """Test encrypt maxmemfrac accepts 5th positional argument of 1/16 total
+ memory for V array"""
+ s = scrypt.encrypt(self.input, self.password, 0.01, 0, 0.0625)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_maxmemfrac_keyword_argument(self):
+ """Test encrypt maxmemfrac accepts keyword argument of 1/16 total memory for
+ V array"""
+ s = scrypt.encrypt(self.input, self.password, maxmemfrac=0.0625,
+ maxtime=0.01)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(m, self.input)
+
+ def test_encrypt_long_input(self):
+ """Test encrypt accepts long input for encryption"""
+ s = scrypt.encrypt(self.longinput, self.password, 0.1)
+ self.assertEqual(len(s), 128 + len(self.longinput))
+
+ def test_encrypt_raises_error_on_invalid_keyword(self):
+ """Test encrypt raises TypeError if invalid keyword used in argument"""
+ self.assertRaises(TypeError, lambda: scrypt.encrypt(self.input,
+ self.password, nonsense="Raise error"))
+
+ def test_decrypt_from_csv_ciphertexts(self):
+ """Test decrypt function with precalculated combinations"""
+ for row in self.ciphertexts[1:]:
+ h = scrypt.decrypt(a2b_hex(bytes(row[5].encode('ascii'))), row[1])
+ self.assertEqual(bytes(h.encode("ascii")), row[0].encode("ascii"))
+
+ def test_decrypt_maxtime_positional(self):
+ """Test decrypt function accepts third positional argument"""
+ m = scrypt.decrypt(self.ciphertext, self.password, self.five_seconds)
+ self.assertEqual(m, self.input)
+
+ def test_decrypt_maxtime_keyword_argument(self):
+ """Test decrypt function accepts maxtime keyword argument"""
+ m = scrypt.decrypt(maxtime=1.0, input=self.ciphertext, password=self.password)
+ self.assertEqual(m, self.input)
+
+ def test_decrypt_maxmem_positional(self):
+ """Test decrypt function accepts fourth positional argument"""
+ m = scrypt.decrypt(self.ciphertext, self.password, self.five_minutes, self.ten_megabytes)
+ self.assertEqual(m, self.input)
+
+ def test_decrypt_maxmem_keyword_argument(self):
+ """Test decrypt function accepts maxmem keyword argument"""
+ m = scrypt.decrypt(maxmem=self.ten_megabytes, input=self.ciphertext, password=self.password)
+ self.assertEqual(m, self.input)
+
+ def test_decrypt_maxmemfrac_positional(self):
+ """Test decrypt function accepts maxmem keyword argument"""
+ m = scrypt.decrypt(self.ciphertext, self.password, self.five_minutes, self.one_megabyte, 0.0625)
+ self.assertEqual(m, self.input)
+
+ def test_decrypt_maxmemfrac_keyword_argument(self):
+ """Test decrypt function accepts maxmem keyword argument"""
+ m = scrypt.decrypt(maxmemfrac=0.625, input=self.ciphertext, password=self.password)
+ self.assertEqual(m, self.input)
+
+ def test_decrypt_raises_error_on_too_little_time(self):
+ """Test decrypt function raises scrypt.error raised if insufficient time allowed for
+ ciphertext decryption"""
+ s = scrypt.encrypt(self.input, self.password, 0.1)
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.decrypt(s, self.password, .01))
+
+
+class TestScryptHash(testm.TestCase):
+
+ def setUp(self):
+ self.input = "message"
+ self.password = "password"
+ self.salt = "NaCl"
+ self.hashes = []
+ base_dir = dirname(abspath(__file__)) + sep
+ hvf = open(base_dir + "hashvectors.csv", "r")
+ hash_reader = reader(hvf, dialect="excel")
+ for row in hash_reader:
+ self.hashes.append(row)
+ hvf.close()
+
+ def test_hash_vectors_from_csv(self):
+ """Test hash function with precalculated combinations"""
+ for row in self.hashes[1:]:
+ h = scrypt.hash(row[0], row[1], int(row[2]), int(row[3]), int(row[4]))
+ hhex = b2a_hex(h)
+ self.assertEqual(hhex, bytes(row[5].encode("utf-8")))
+
+ def test_hash_buflen_keyword(self):
+ """Test hash takes keyword valid buflen"""
+ h64 = scrypt.hash(self.input, self.salt, buflen=64)
+ h128 = scrypt.hash(self.input, self.salt, buflen=128)
+ self.assertEqual(len(h64), 64)
+ self.assertEqual(len(h128), 128)
+
+ def test_hash_n_positional(self):
+ """Test hash accepts valid N in position 3"""
+ h = scrypt.hash(self.input, self.salt, 256)
+ self.assertEqual(len(h), 64)
+
+ def test_hash_n_keyword(self):
+ """Test hash takes keyword valid N"""
+ h = scrypt.hash(N=256, password=self.input, salt=self.salt)
+ self.assertEqual(len(h), 64)
+
+ def test_hash_r_positional(self):
+ """Test hash accepts valid r in position 4"""
+ h = scrypt.hash(self.input, self.salt, 256, 16)
+ self.assertEqual(len(h), 64)
+
+ def test_hash_r_keyword(self):
+ """Test hash takes keyword valid r"""
+ h = scrypt.hash(r=16, password=self.input, salt=self.salt)
+ self.assertEqual(len(h), 64)
+
+ def test_hash_p_positional(self):
+ """Test hash accepts valid p in position 5"""
+ h = scrypt.hash(self.input, self.salt, 256, 8, 2)
+ self.assertEqual(len(h), 64)
+
+ def test_hash_p_keyword(self):
+ """Test hash takes keyword valid p"""
+ h = scrypt.hash(p=4, password=self.input, salt=self.salt)
+ self.assertEqual(len(h), 64)
+
+ def test_hash_raises_error_on_p_equals_zero(self):
+ """Test hash raises scrypt error on illegal parameter value (p = 0)"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, p=0))
+
+ def test_hash_raises_error_on_negative_p(self):
+ """Test hash raises scrypt error on illegal parameter value (p < 0)"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, p=-1))
+
+ def test_hash_raises_error_on_r_equals_zero(self):
+ """Test hash raises scrypt error on illegal parameter value (r = 0)"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, r=0))
+
+ def test_hash_raises_error_on_negative_r(self):
+ """Test hash raises scrypt error on illegal parameter value (r < 1)"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, r=-1))
+
+ def test_hash_raises_error_r_p_over_limit(self):
+ """Test hash raises scrypt error when parameters r multiplied by p over limit 2**30"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, r=2, p=2 ** 29))
+
+ def test_hash_raises_error_n_not_power_of_two(self):
+ """Test hash raises scrypt error when parameter N is not a power of two {2, 4, 8, 16, etc}"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, N=3))
+
+ def test_hash_raises_error_n_under_limit(self):
+ """Test hash raises scrypt error when parameter N under limit of 1"""
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, N=1))
+ self.assertRaises(scrypt.error,
+ lambda: scrypt.hash(self.input, self.salt, N=-1))
+
+if __name__ == "__main__":
+ testm.main()
diff --git a/tests/test_scrypt_py2x.py b/tests/test_scrypt_py2x.py
new file mode 100644
index 0000000..811cf37
--- /dev/null
+++ b/tests/test_scrypt_py2x.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+from sys import version_info
+
+if ((version_info > (3, 2, 0, 'final', 0)) or
+ (version_info > (2, 7, 0, 'final', 0) and version_info < (3, 0, 0, 'final', 0))):
+ import unittest as testm
+else:
+ try:
+ import unittest2 as testm
+ except ImportError:
+ print("Please install unittest2 to run the test suite")
+ exit(-1)
+
+import scrypt
+
+
+@testm.skipIf(version_info > (3, 0, 0, 'final', 0), "Tests for Python 2 only")
+class TestScryptForPython2(testm.TestCase):
+
+ def setUp(self):
+ self.input = "message"
+ self.password = "password"
+ self.unicode_text = '\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6'.decode('utf-8')
+
+ def test_py2_encrypt_fails_on_unicode_input(self):
+ """Test Py2 encrypt raises TypeError when Unicode input passed"""
+ self.assertRaises(TypeError, lambda: scrypt.encrypt(self.unicode_text, self.password))
+
+ def test_py2_encrypt_fails_on_unicode_password(self):
+ """Test Py2 encrypt raises TypeError when Unicode password passed"""
+ self.assertRaises(TypeError, lambda: scrypt.encrypt(self.input, self.unicode_text))
+
+ def test_py2_encrypt_returns_string(self):
+ """Test Py2 encrypt returns str"""
+ e = scrypt.encrypt(self.input, self.password, 0.1)
+ self.assertTrue(isinstance(e, str))
+
+ def test_py2_decrypt_returns_string(self):
+ """Test Py2 decrypt returns str"""
+ s = scrypt.encrypt(self.input, self.password, 0.1)
+ m = scrypt.decrypt(s, self.password)
+ self.assertTrue(isinstance(m, str))
+
+ def test_py2_hash_returns_string(self):
+ """Test Py2 hash return str"""
+ h = scrypt.hash(self.input, self.password)
+ self.assertTrue(isinstance(h, str))
+
+if __name__ == "__main__":
+ testm.main()
diff --git a/tests/test_scrypt_py3x.py b/tests/test_scrypt_py3x.py
new file mode 100644
index 0000000..e03e098
--- /dev/null
+++ b/tests/test_scrypt_py3x.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+from sys import version_info
+
+if ((version_info > (3, 2, 0, 'final', 0)) or
+ (version_info > (2, 7, 0, 'final', 0) and version_info < (3, 0, 0, 'final', 0))):
+ import unittest as testm
+else:
+ try:
+ import unittest2 as testm
+ except ImportError:
+ print("Please install unittest2 to run the test suite")
+ exit(-1)
+
+import scrypt
+
+
+@testm.skipIf(version_info < (3, 0, 0, 'final', 0), "Tests for Python 3 only")
+class TestScryptForPy3(testm.TestCase):
+
+ def setUp(self):
+ self.input = "message"
+ self.password = "password"
+ self.byte_text = b'\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6'
+ self.unicode_text = self.byte_text.decode('utf-8', "strict")
+
+ def test_py3_encrypt_allows_bytes_input(self):
+ """Test Py3 encrypt allows unicode input"""
+ s = scrypt.encrypt(self.byte_text, self.password, 0.1)
+ m = scrypt.decrypt(s, self.password)
+ self.assertEqual(bytes(m.encode("utf-8")), self.byte_text)
+
+ def test_py3_encrypt_allows_bytes_password(self):
+ """Test Py3 encrypt allows unicode password"""
+ s = scrypt.encrypt(self.input, self.byte_text, 0.1)
+ m = scrypt.decrypt(s, self.byte_text)
+ self.assertEqual(m, self.input)
+
+ def test_py3_encrypt_returns_bytes(self):
+ """Test Py3 encrypt return bytes"""
+ s = scrypt.encrypt(self.input, self.password, 0.1)
+ self.assertTrue(isinstance(s, bytes))
+
+ def test_py3_decrypt_returns_unicode_string(self):
+ """Test Py3 decrypt returns Unicode UTF-8 string"""
+ s = scrypt.encrypt(self.input, self.password, 0.1)
+ m = scrypt.decrypt(s, self.password)
+ self.assertTrue(isinstance(m, str))
+
+ def test_py3_hash_returns_bytes(self):
+ """Test Py3 hash return bytes"""
+ h = scrypt.hash(self.input, self.password)
+ self.assertTrue(isinstance(h, bytes))
+
+if __name__ == "__main__":
+ testm.main()