Encryption with Encryption Key returns different output with the same data

Hi @Agobin,

If you’re doing password authentication, this is a somewhat dangerous way to do it! Is there a reason you’re not using the Users Service, which has this all built in?

This post got long, and it still doesn’t cover all the considerations in building password-based authentication. This is something with lots of sharp edges, and I strongly, strongly recommend using the Users service if you can.


The layout you’re proposing uses symmetric encryption for the passwords, which means you (or any administrative user) can decrypt any password you want! This generally isn’t what your users expect from you, and is generally considered bad hygiene.

Instead, you should be using a strong one-way function, such as bcrypt – “one way” means that you can’t simply decrypt it. If you have the password, you can check it, but that’s all. However, bcrypt isn’t repeatable: if you give it the same input twice, you’ll get two different outputs, so you still can’t use it in the sort of query you’re doing.

(This is for really good reasons! If it produced the same output every time for the same password, it would be easy to spot which users in your database had the same password. Plus, you could compute an up-front table of the hashes of, say, the 100 million most common passwords, which would make it easy to break the hashes if they ever leaked. This is one reason why using “ordinary” hashing algorithms, such as SHA256, isn’t a good idea for password storage. So instead, bcrypt uses a “salt”: a random value that’s different every time, so that encoding the same password twice gives different results. bcrypt also does a deliberately slow computation, so that brute-forcing the hashes – by trying every password in the world – is slow.)

So, how do you use the bcrypt module? Again, check the docs, but here’s an example:

import bcrypt

password = b"super secret password"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())

# Now store the hashed password, not the original!
# When it's time to check the password, retrieve the hash from the database
# (use the username as your selection criterion, not the hash), and do:

if bcrypt.checkpw(password, hashed):
  print("It matched!")
else:
  print("It didn't match")

The bcrypt module is available in every server-side environment, including Basic Python.

(Note that bcrypt is expecting a bytes object, not a str object. If you’re giving it a string, you’ll want to do password.decode().)


This is not a complete guide to password authentication; there are a lot more questions than just the hashing algorithm, and lots of subtleties, and getting it wrong can lead to moderate-to-severe security vulnerabilities. This is why we built a robust password implementation into the Users Service, and we recommend you use that rather than rolling your own!

Again, please use the Users Service if you can!

5 Likes