Package: django-scrypt
Django-Scryptis aScrypt-enabled password hasher forDjangover. 1.4/1.5.WarningThe encoded hash format has changed in version 0.2.0. This change is
backwards incompatible. Please read the notice in theCaveatssection.Scryptis a sequential memory-hard key derivation function. This software allowsDjangoto access low-level bindings of theScryptkey derivation function viaPy-Scrypt.InstallationWarningThis is alpha software under active development and as such it is not suitable for production use. It was tested only
onPython 2.6/2.7 on a 32-bit Mac and 64-bit CentOS 6.
It probably will not run on Python
2.5 sincePy-Scryptdoesn’t run on interpreters earlier than
Python 2.6.InstallingDjango-Scryptinto your system-wide Python’ssite-packagesdirectory is not recommended. Instead, usevirtualenvandvirtualenvwrapperto create isolated virtual Python environments and then install this software into the isolatedvirtualenv’ssite-packagesdirectory.NoteYou should installDjango 1.4andpy-scryptprior to installingDjango-ScryptUsing source tarballsDownload theDjango-Scryptsource tarball from Pypi (Python
Package Index)http://pypi.python.org/pypi/django-scrypt/Decompress it and make it your working directory:$ tar zxvf django-scrypt-0.2.3.tar.gz
$ cd django-scrypt-0.2.3Install it into yoursite-packagesdirectory (if you install to the
system’ssite-packagesyou will probably need to be root or you will
probably need to usesudoto copy into protected directories):$ python setup.py installTest your installation:$ python setup.py testUsing Pip and PypiIf you are installing to the system-widesite-packagesthen you
will probably need to be root or you will probably need to usesudo.Use thepipcommand to install from Pypi:$ pip install django-scryptUsing a Clone from BitBucketSince this is nascent software, you may want to get the most recent
development version.UseMercurialto clone the
repository:$ hg clone https://bitbucket.org/kelvinwong_ca/django-scrypt
$ cd django-scryptInstall it into yoursite-packages(if you install it in your system’ssite-packagesyou will probably need to be root or you will probably
need to usesudo):$ python setup.py installTest your installation (seriously,pleasedo this):$ python setup.py testKeep in mind that the development tip will always be the least stable and the
least tested version of the software. Please excuse the mess.UsageBasic UsageWarningThis software depends onPy-Scryptversion 0.5.5 to reveal
theScrypthashing function. Unfortunately, it contains a bug
that can result in incorrect hashing when run on 64-bit Linux systems. View
thePy-Scryptissue tracker for the latest information on this issue.[1][1]SeePy-ScryptIssue 6To useScryptas your default password storage algorithm inDjango 1.4/1.5,
install it and make the following changes. In yourDjango 1.4/1.5application’ssettings.pyfile, modify thePASSWORD_HASHERStuple (or add it if it
is missing) to includeScryptPasswordHasheras the first hasher in the
tuple. It needs to be at the very top.For example:PASSWORD_HASHERS = (
  'django_scrypt.hashers.ScryptPasswordHasher',
  'django.contrib.auth.hashers.PBKDF2PasswordHasher',
  'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
  'django.contrib.auth.hashers.SHA1PasswordHasher',
  'django.contrib.auth.hashers.MD5PasswordHasher',
  'django.contrib.auth.hashers.CryptPasswordHasher',
)You have now changed your app to useScryptas the default storage
algorithm. As users login to your system they will automatically upgrade their hashed passwords toScrypthashes.NoteYou need to keep the other hasher entries in this list or elseDjangowon’t be able to upgrade the passwords!Advanced UsageIf you use this software in a resource constrained environment or if you want a higher degree of protection, you can create customScryptPasswordHashersby subclassing the providedScryptPasswordHasher. Subclassing will allow you to tune theScryptparameters to meet your needs.The first thing to do is create a new custom hasher. Let’s assume that you create a new file namedmy_hashers.pyand you put it into your application root (my_app). In that file you can subclass the default hasher:from django_scrypt.hashers import ScryptPasswordHasher

class BigMemNScryptHasher(ScryptPasswordHasher):
    """This hasher is tuned to use lots of memory
    (128 * 2 ** 15 * 8) == 33554432 or ~32mb
    """
    algorithm = "bigN"
    N = 15You can change any (or all) of the class variablesN,r, orp. Thealgorithmclass variablemustalso be changed to a short unique string since it is used to identify and upgrade the hashing scheme in the stored password hash.To useBigMemNScryptHasheras your default password storage algorithm make the following changes. In your application’ssettings.pyfile, modify thePASSWORD_HASHERStuple (or add it if it
is missing) to includeBigMemNScryptHasheras the first hasher in the
tuple. It needs to be at the very top:PASSWORD_HASHERS = (
  'my_app.my_hashers.BigMemNScryptHasher',
  'django.contrib.auth.hashers.PBKDF2PasswordHasher',
  'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
  'django.contrib.auth.hashers.SHA1PasswordHasher',
  'django.contrib.auth.hashers.MD5PasswordHasher',
  'django.contrib.auth.hashers.CryptPasswordHasher',
)If you want to change the parameters again in the future, simply repeat the process with another subclass and another uniquealgorithmclass variable. Add it to the top of the tuple and your users will have their password hashes migrated to the new scheme as they log in.Scrypt ParametersScrypttakes three tuning parameters:N,randp.
They affect memory usage and running time. Memory usage is approximately128 * r * Nbytes.[2]These are the default values:Nexp = lb(N) = 14, r = 8 and p = 1
where lb is logarithm base 2Django-ScryptstoresNexpin the encoded hash, but notN. The positive integerNexpis the exponent used to generateNwhich is calculated as needed (N = 2 ** Nexp). Doing this saves space in the database row. These default values lead toScryptusing128 * 8 * 2 ** 14 = 16Mbytes of memory.The values ofN,randpaffect running time proportionately; however,pcan be used to independently tune the running time since it has a smaller influence on memory usage.The final parameterbuflenhas been proposed forPy-Scryptbut is not implemented. The value will be used to change the size of the returned hash. Currently,Py-Scrypt’shashfunction returns a message digest of length 64-bytes or 512-bits.[2]Adapted from Falko Peters’Crypto.Scrypt package for HaskellCaveatsHash Format Changes As ‘N’ RemovedIn an attempt to shorten the length of the encoded hash, I removed theN-value and replaced it with anN-exponent value namedNexp.
The reason for this is thatNmust be a power of
two {2, 4, 8, … 16384, …etc…} and those digits take up room in a
128 character hash storage space. It makes more sense to me to store the exponent and just make the actual integer on the fly.N == 16384 == 2 ** 14 therefore Nexp == 14The old encoded hash format that got stored inDjango’sdatabase wasscrypt$salt$16384$8$1$64$Base64Hash==The new and shorter encoded hash format isscrypt$salt$14$8$1$64$Base64Hash==The good news is that “14” is three characters shorter than “16384”. The bad news
is that this introduces a backwards incompatible change as of version 0.2.0.If you see your application generatingHTTP 500 Server Errorswith anExceptionraised witherror: ‘hash parameters are wrong (r*p should be < 2**30, and N should
be a power of two > 1)’then you should suspect that an old hash is tellingScryptto useN = 2 ** 16384which is way, way, way too large. The
solution is to replace the 16384 in the old hashes with 14. You might have to alter your database manually or write some custom code to fix this change.Django Password Field Character Length LimitsBy default,Djangolimits password field lengths to 128 characters. Using
the default settings inDjango-ScryptwithDjango’ssalting
implementation should yield encoded hashes less than 128 characters (approx 119 characters); however, if you override theScryptPasswordHasherclass variables you might end up overflowing the default password field.The solution is to increase the size of the password field using SQL. You
should consult your database documentation for the correct commands necessary to alter your database.Bugs! Help!!If you find any bugs in this software please report them via the BitBucket
issue tracker[3]or send an email tocode@kelvinwong.ca. Any serious
security bugs should be reported via email only.[3]Django-Scrypt issue trackerhttps://bitbucket.org/kelvinwong_ca/django-scrypt/issuesThank-youThank-you for taking the time to evaluate this software. I appreciate
receiving feedback on your experiences using it and I welcome code
contributions and development ideas.http://www.kelvinwong.ca/codersThanks to Dr Colin Percival for his originalScryptsoftware[4],
also to Magnus Hallin for thePy-ScryptPython module[5].[4]Visithttp://www.tarsnap.com/scrypt.html[5]Visithttp://pypi.python.org/pypi/scrypt/