#!/usr/bin/env python import random import string import crypt #import md5 import hashlib import base64 class CryptUtility: CRYPT_TYPE = 6 # SHA-512 (man crypt) SALT_CHARACTERS = string.lowercase + string.uppercase + string.digits SALT_DELIMITER = '$' SALT_LENGTH_IN_BYTES = 4 PBKDF2_ENCRYPTION = 'sha1' # use SHA-1 for compatibility with java PBKDF2_KEY_LENGTH_IN_BYTES = 24 PBKDF2_ITERATIONS = 1003 @classmethod def getRandomWord(cls, length): return ''.join(random.choice(CryptUtility.SALT_CHARACTERS) for i in range(length)) @classmethod def cryptPassword(cls, password): """ Return crypted password. """ #calculator = md5.md5() #calculator.update(salt) #md5Salt = calculator.hexdigest() #return crypt.crypt(cleartext, md5Salt) salt = CryptUtility.getRandomWord(CryptUtility.SALT_LENGTH_IN_BYTES) salt = '%s%s%s%s%s'.format(CryptUtility.SALT_DELIMITER, CryptUtility.CRYPT_TYPE, CryptUtility.SALT_DELIMITER, salt, CryptUtility.SALT_DELIMITER) return crypt.crypt(password, salt) @classmethod def verifyPassword(cls, password, cryptedPassword): """ Verify crypted password. """ return cryptedPassword == crypt.crypt(password, cryptedPassword) @classmethod def cryptPasswordWithPbkdf2(cls, password): """ Crypt password with pbkdf2 package and encode with b64. """ salt = CryptUtility.getRandomWord(CryptUtility.SALT_LENGTH_IN_BYTES) return cls.saltAndCryptPasswordWithPbkdf2(password, salt) @classmethod def saltAndCryptPasswordWithPbkdf2(cls, password, salt): """ Crypt salted password with pbkdf2 package and encode with b64. """ cryptedPassword = hashlib.pbkdf2_hmac( CryptUtility.PBKDF2_ENCRYPTION, password, salt, CryptUtility.PBKDF2_ITERATIONS, CryptUtility.PBKDF2_KEY_LENGTH_IN_BYTES) encodedPassword = base64.b64encode(cryptedPassword) return '%s%s%s' % (salt, CryptUtility.SALT_DELIMITER, encodedPassword) @classmethod def verifyPasswordWithPbkdf2(cls, password, cryptedPassword): """ Verify crypted password. """ # Get salt salt = '%s' % cryptedPassword.split(CryptUtility.SALT_DELIMITER)[0] # Verify crypted password return cryptedPassword == cls.saltAndCryptPasswordWithPbkdf2(password, salt) ####################################################################### # Testing. if __name__ == '__main__': import sys #password = "dm" password = sys.argv[1] print 'Clear text: ', password #cryptedPassword = CryptUtility.cryptPassword(password) #print 'Crypted: ', cryptedPassword #isVerified = CryptUtility.verifyPassword(password, cryptedPassword) #print 'Verify: ', isVerified cryptedPassword = CryptUtility.cryptPasswordWithPbkdf2(password) print 'Crypted: ', cryptedPassword isVerified = CryptUtility.verifyPasswordWithPbkdf2(password, cryptedPassword) print 'Verify: ', isVerified