Skip to content

Instantly share code, notes, and snippets.

@ioparaskev
Created February 10, 2015 21:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ioparaskev/a95338759b239b215340 to your computer and use it in GitHub Desktop.
Save ioparaskev/a95338759b239b215340 to your computer and use it in GitHub Desktop.
Dovecot Salted SHA 512 encoder/decoder for Python 3
#This is a porting of https://gist.github.com/garrettreid/8329796
# to Python 3 with some more additions (time compare, dialogs etc)
# for Python 2.x use the above gist
from hashlib import sha512
import os
import base64
from operator import _compare_digest as constant_time_compare
class SSHA512Hasher:
def __init__(self, salt=os.urandom(16)):
self.salt = salt
def encode(self, password, salt=None):
assert password is not None
if not salt:
salt = self.salt
sha = sha512()
password = password.encode('utf-8')
sha.update(password)
sha.update(salt)
ssha512 = base64.b64encode(sha.digest() + salt)
# Print it out with a prefix for Dovecot compatibility
return "{{SSHA512}}{}".format(ssha512.decode('utf-8'))
def verify(self, password, encoded):
striped = encoded.replace('{SSHA512}', '')
decoded = base64.b64decode(striped)
#we don't care how big salt is. everything after 64 is salt
salt = decoded[64::]
encoded_2 = self.encode(password, salt)
return constant_time_compare(encoded, encoded_2)
if __name__ == '__main__':
shahasher = SSHA512Hasher()
choice = input('Enter [a] for encode\n[b] for decode:\n')
password = input('Enter a password:\n')
if choice is 'a':
print(shahasher.encode(password))
elif choice is 'b':
dovhash = input('Enter the hash with the {{SSHA512}} prefix:\n')
if shahasher.verify(password, dovhash):
print("It's a match!")
else:
print("Pass doesn't match the hash!")
else:
print('You entered an incorrect option!\nExiting......')
exit(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment