This case we will use PyNaCl (Networking and Cryptography) library, and which is a Python binding to libsodium. We will hash a password using SHA-256 and SHA-512, and also create a KDF (Key Derivation Function) using scrypt and Argon2. With Argon2, we have a memory robust key derivation function from a password and a salt value. Argon2 was designed Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich is a key derivation function (KDF), where were we can create hashed values of passwords, or create encryption keys based on a password. It was a winner of the Password Hashing Competition in July 2015, and is robust against GPU and side channel attacks [paper]. We will also use the salt value as a key for the key-hash method of SIPHash24.
Sodium: NaCl - Hashing and KDF (scrypt and Argon2) |
Outline
With many fast hashing methods, such as MD5, we can now get billions or even trillions or hashes per second, where even 9 or 10 character passwords can be cracked for a reasonable financial cost. This includes salting of the password, as the salt is contained with the hashed password, and can be easily cracked with brute force (or dictionaries). The alternative is to use a hashing method which has a cost in memory, and for CPU processing. We also want to create a method which makes it difficult to apply parallel threads (and thus run it on GPUs). So a step forward is Argon2 which was designed Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich as a key derivation function. It was a winner of the Password Hashing Competition in July 2015. It is resistant to GPU attacks, and also has a memory cost. The costs include: execution time (CPU cost); memory required (memory cost); and degree of parallelism.
The parameters include:
- Password (P): Defines the password bytes to be hashed
- Salt (S): Defines the bytes to be used for salting.
- Parallelism (p): Defines the number of thread that are required for the parallelism.
- TagLength (T): Define the number of bytes to return for the hash.
- MemorySizeKB (m): Amount of memory (in KB) to use.
$argon2id$v=19$m=8,t=3,p=1$yh3bPPtc2tSnm8xpK1RZbw$CBE1uk3HK23zkotoY9280NWemhMj6FnljoDMSZ8PZ58
Coding
The code is:
import nacl.hash import nacl.hashlib import nacl.pwhash import nacl.encoding import binascii import sys from os import urandom password='hello' salt='' if (len(sys.argv)>1): password=str(sys.argv[1]) if (len(sys.argv)>2): salt=str(sys.argv[2]) salt=salt.zfill(16) print("Password: ",password) print("Salt: ",salt) salt=salt.encode() password=password.encode() mlevel=nacl.pwhash.MEMLIMIT_INTERACTIVE olevel=nacl.pwhash.OPSLIMIT_INTERACTIVE print ("\nSHA256: ",nacl.hash.sha256(password)) print ("SHA512: ",nacl.hash.sha512(password)) print ("\nBlake2b: ",nacl.hashlib.blake2b(password,salt=salt).hexdigest()) print ("Scrypt: ",binascii.hexlify(nacl.hashlib.scrypt(password,salt, n=2, r=8, p=1, maxmem=2**25, dklen=64))) print("\nArgon2id") print(binascii.hexlify(nacl.pwhash.argon2id.kdf(size=32,password=password,salt=salt,opslimit=3,memlimit=8192))) print(nacl.pwhash.argon2id.str(password=password,opslimit=3,memlimit=8192)) print("\nArgon2i") print(binascii.hexlify(nacl.pwhash.argon2i.kdf(size=32,password=password,salt=salt,opslimit=3,memlimit=8192))) print(nacl.pwhash.argon2i.str(password=password,opslimit=3,memlimit=8192)) salt=salt.zfill(32) print("\nScrypt") print(binascii.hexlify(nacl.pwhash.scrypt.kdf(size=32,password=password,salt=salt,opslimit=olevel,memlimit=mlevel))) print(nacl.pwhash.scrypt.str(password=password,opslimit=3,memlimit=mlevel))
A sample run is:
Password: hello Salt: 0000000000000000 SHA256: b'2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824' SHA512: b'9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043' Blake2b: df4307e2c39f9547f315c3c7e993365b1de4f9572e6d3b1149215dbdfe1a9c16 Scrypt: b'e11f96489aa3acaeebd7b921932cacead0a57481422e8f401d39f1e7b39da489e73947c7ebc80c8cb132a08805a814760406078c3914f4d5f18f3af17f9f3138' SIPHash24: b'b9e9ddce8e7df54a' Argon2id b'bd489e46c06cef832330b9b9b4ac1d582af8fd8428cfcf6c51d7a75c409aa1c8' b'$argon2id$v=19$m=8,t=3,p=1$yh3bPPtc2tSnm8xpK1RZbw$CBE1uk3HK23zkotoY9280NWemhMj6FnljoDMSZ8PZ58' Argon2i b'e24e2ec77a165493e4dbd752356b0e02984d88f78a52ab3e6400f56a5bb31e45' b'$argon2i$v=19$m=8,t=3,p=1$+dPKo4mmybIguS2KrDAKiA$15281SkyU7jfcaonlrRdFnYeGEUe2COs0N2ALjoWMm4' Scrypt b'b293fcf7d40775326828b39fe78fbe89ff8d0e87b39a1f3d6b0f48065da49103' b'$7$86..../....5YbzrYBrIXJIgLsdePGYwQVzhncMPDfxzj6ras5uCI4$7YoUI9M2e5XPAEgYDPpFEJ5hxboQi/I57LJT4gYoLu3'