How to re-add "unique" salt when user logs in? - encryption

I am learning about hashing and encryption and can’t seem to understand this:
Client: New user logs in => Creates password => Sent to a server in plain text
Server: Server generates a random "salt" => plain text and salt are unified => Hash function (e.g. SHA-3) hashes the password+salt into a hash => Hash is stored in DB.
Client: Same user logs out and logs in => Password sent to a server in plain text.
Server: Password needs to re-add the same salt it generated when creating the account to get the same hash.
How does the server generate that same random and unique salt?
Is the salt stored on a different DB altogether?
If a DB is compromised the hackers would also gain access to the salt and just brute force rainbow tables with the salt and unhash them.

The salt that was randomly generated must be stored in the database and linked to the user that logged in. It could be simply added as another column in the user table.
In a typical setting, the salt and the password (or its version after
key stretching) are concatenated and processed with a cryptographic
hash function, and the output hash value (but not the original
password) is stored with the salt in a database
Source: https://en.wikipedia.org/wiki/Salt_(cryptography) retrieved 19/02/21
The generation of the salt depends on which technology you are using. The following stack overflow answer has an example for PHP:
Can we use uniqid() to generate a unique Salt in PHP
The password should also never be sent in plain text to the server. This can be done via HTTPS for example

When the user logs in again. The password is sent to server side along with email.
The email is used to fetch the user record and then the Hash value saved against that email is compared with the new hash (salt + password entered).
The validate function method matches the 2 different hash values and checks if password entered was same or not.
For example, I am using bcrypt in Node JS and it has a method compareSync which matches the entered password with the saved hash
bcrypt.compareSync(password, databaseHash);

Related

How to remove Db2 encryption password in current connection

Db2 allows to set a password in the connection using
SET ENCRYPTION PASSWORD 'mysecretpw'
This avoids having to set the password on each ENCRYPT() / DECRYPT() usage.
However, how can I remove the password after I finished my work so that other parts of code that work with the same connection are not able to use my password ?
I didn't find a 'REMOVE/DROP ENCRYPTION PASSWORD'.
Setting the password to an empty string SET ENCRYPTION PASSWORD ''caused problems when my code was invoked multiple times in the same process: the second invocation got 'NO PASSWORD SET' SQL20143N / SQLSTATE 51039 even though it did set the correct password again using "SET ENCRYPTION PASSWORD 'mysecretpw'" again before using ENCRYPT/DECRYPT ... Db2 also says that you have to specify a password between 6 and 127 bytes ...
Setting an arbitrary string as new password (e.g. blanks) is also not ideal, as this does not allow Db2 to detect 'no password set' conditions so that you don't realize that you are encrypting / decrypting with a wrong password ...
So how to clear the password correctly ?
The Db2 LUW documentation (at version 11.1) for SET ENCRYPTION PASSWORD does not state it explicitly but the product allows you to set the password to an empty string with the result that subsequent encrypt/decrypt actions in that connection will return -20143 sqlcode. When I test this behaviour with the CLP it behaves as expected on Db2 LUW.
So while both Db2 for Z/OS and Db2 for i-series for SET ENCRYPTION PASSWORD explicitly mention the empty string behaviour for the password (and the Db2 LUW knowledge center does not), it appears all three code bases have the same behaviour as regards the consequence of setting the password to the empty string.
If you have a testcase that proves you get an -20143 sqlcode even after using SET ENCRYPTION PASSWORD to a valid good password, then perhaps you should publish that testcase or open a PMR with IBM. If your code is multi threaded , you may get unexpected results as the password is in special register and changing it is not under transaction control, so there may be timing issues.
Removing the password seems to be possible either via disconnecting the session or setting it to an empty string in a single-connection scenario, and with the CLP the product appears to behave as expected for me when I set the password to an empty string, and subsequently set it to a valid password for the same connection.

LUKS change encryption key

I found on this forum some very interesting content for problem that I have, but I don't found answer for my question.
To change encryption password I can use command:
cryptsetup luksChangeKey /dev/sda2
... and that works. But how to encrypt /dev/sda2 partition again with new password?
If my old password is compromised and I only change password, stored data is encrypted with old password not with new.
The LUKS partition itself is not encrypted with your password: it is encrypted with a strong "master key" randomly calculated upon volume creation. Your old and new passwords only serve to encrypt the "master key". Unfortunately both passwords and the "master key" as often referred to as "keys" hence your (and others') confusion.
When in the old days cryptsetup did not rely on LUKS, every time you changed your cryptsetup password the entire disk would have to be re-encrypted!
Nowdays you only have to change your master key if someone also gains physical or administrative access to the encrypted device while the password is valid.
p.s. if not relying on temporary storage but having free space, the LUKS master key may be "changed" by shrinking a LUKS volume via "cryptsetup resize", creating another volume, moving data, deleting the first volume and expanding the second volume.

Hashing using SHA1 as inner-most hash in a chain

A client program (over which I have no control) is authenticating by sending me a password, hashed as SHA1(password).
I'm reluctant to store the password hashed using only SHA1 in my database, so I'm proposing to store passwords in the database hashed as SHA256(SHA1(password)) (where the password is hashed over multiple iterations using PBKDF-2 or something similar).
My question is: is there anything insecure about the inner-most hash using SHA1 in this scenario? I realise that the probability of collisions will be increased, but since this is just for storing passwords in the database I don't think I need to be concerned about that. Is there anything else that I'm missing?
Consider adding a salt which is unique-per-row before doing the final encryption. Example:
Lets say that you receive W6ph5Mm5Pz8GgiULbPgzG37mj9g= (a SHA1'd encryption of "password"). That is associated with a User, who should have a unique key, such as a UserID and/or UserName.
My suggestion - to avoid collision - would be to do a conversion of the Bytes to a Base64String (in C# this would be Convert.ToBase64String( byteVariable ) - then concatenate onto the string the user's unique-ID (making the new string something like:
W6ph5Mm5Pz8GgiULbPgzG37mj9g=+103 (where I added +103 to reflect the user's ID) - then apply your SHA256 algorithm. This will produce: mNXRjWsKJ7V+BHbAuwJJ7neGT+V1IrLQSQXmb4Vv1X8= - which you can store in your database. A SHA256 hash - which eliminates the collisions from the less-safe SHA1 algorithm.
And - since you are using 1-way encryption - when you go to check whether the password is valid in the future, you simply append the user's ID again before checking.
If the client always sends you the same password, simply SHA1 hashed, then the SHA1 hash output is the password, to all intents and purposes. Treat it and store it the same way you would any other password, such as by using PBKDF2, SCrypt, or BCrypt.

Is brute force the only reasonable approach to detecting encryption?

An old version of an application has some passwords stored in the clear in its database. I have written an updated version that encrypts the passwords when new entries are made, but I don't have direct access to the database to manually encrypt the entries that already exist. When the update goes live, it will try to decrypt the plaintext passwords, and crash.
Short of doing something drastic like deleting all the existing data, the only other approach I can think of is this (wrapper pseudocode called when the password data is used.):
# data refers to the password data, either encrypted or plain
if data length < AES.block_size:
# (Shorter than initialization vector, definitely not encrypted.)
open database and replace password entry with encrypt(data)
login(username, data)
else:
try: # try plaintext first
login(username, data)
except AuthenticationError:
login(username, decrypt(data))
else: #plain text worked, encrypt data for future use.
open database and replace password entry with encrypt(data)
It seems a shame to keep this code around to solve a problem that goes away after it runs once. Is there any other approach that might work to ensure the passwords are encrypted and only decrypt the ones that need it?
In this scenario I do one of the following, depending on the client and the system involved:
Set up the encrypted password code, delete all existing passwords, and make everyone enter a new password. I prefer this because the passwords were plain and over time may have been seen or shared.
Run a one-time script to encrypt every password in the system. This way there is never a mix.
Have newer encrypted passwords prefixed with the encryption method, e.g. "SHA1:". You run the risk of someone having that same text as the start of their password, but it is unlikely.

Convert ASP.NET Membership Passwords from Encrypted to Hashed

I've developed a website that uses ASP.NET membership. Based on comments from previous sites, I decided to encrypt passwords so they could be recovered for users who forgot them.
However, the new site (which now has over 500 registered users) has brought me some criticism that the industry standard is really to hash passwords.
However, after a fairly extensive search, I have been unable to find anything about how to convert existing users' passwords from encrypted to hashed.
I know I can change the web.config file, and new users' passwords will use the new format. But it does nothing to update the existing users.
Note: I previously asked a similar question but mostly just got a debate about which is better, encrypted or hashed. I'm past that discussion but I've been unable to find a way to convert them without losing the hundreds of users already registered.
it seems you already know how to decrypt the passwords and change the web.config file, but you're stuck with how to implement the rest of the process.
using ILSpy, here's how to generate the salt for each user:
byte[] array = new byte[16];
new RNGCryptoServiceProvider().GetBytes(array);
return Convert.ToBase64String(array);
once you have the salt, here's how to generate the password:
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] array = Convert.FromBase64String(salt);
byte[] array2 = new byte[array.Length + bytes.Length];
Buffer.BlockCopy(array, 0, array2, 0, array.Length);
Buffer.BlockCopy(bytes, 0, array2, array.Length, bytes.Length);
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) {
return Convert.ToBase64String(sha1.ComputeHash(array2));
}
where pass is the plain-text password you calculated, and salt is the string calculated in the first code snippet above. the default algorithm is SHA1, if you're wondering why it's being used.
since this is a one-time process, i would write a HTTP handler to manually update the database during a short, scheduled maintenance period - hopefully you have that luxury. (obviously make a backup and test first). you need to update the following fields in the aspnet_Membership table:
Password - calculated above
PasswordFormat - 1
PasswordSalt - calculated above
never had to do anything like this, but hopefully that will get you started :)
IMHO, Greg's response (and the associated comments) on your previous question (Changing passwordFormat from Encrypted to Hashed) is the way to go. Essentially, you want to:
Add a hashed membership provider
Loop through all of the encrypted password users,
For each one decrypt the password, create the hash, store it, delete the encrypted version from the database, and move on.
When you are done, all of the encrypted password users should be converted to hashed.
Maybe I'm missing something here, but it should be pretty simple. Create a process to decrypt the password, then salt accordingly and store the hash of the salt + user's decrypted password in the database. Obviously you don't want to be hashing the user's encrypted password. Don't forget to store the salt too.

Resources