Rust: How to hash a string? - rust

I'm trying to create a console application in Rust where you have to enter a password to access the rest of the file, so I wanted to ensure that you can't just read the file to find the password, so I wanted to store the password as a hash, so its (improbably) irreversable.
I looked up hashing in Rust, but they seem to be only usable with structs, while I'm trying to insert a String. Is a struct the only way to be able to do this?

The built-in Hash class in Rust is designed to process data for the purpose of entry into a HashMap or HashSet. This isn't suitable for password verification.
If you want to perform password verification, you should use a password hash like Argon2id or scrypt. You can find these in the argon2 and scrypt crates. Password hashes always take bytes, so you will want to access your String as a &[u8]. The password_hash crate provides traits you can use to turn these into a serialized password.
If your goal is to encrypt the remainder of the file with the password, then you should use one of the bindings to NaCl. This library has primitives that are designed to be secure. You would use the password hash functionality with a random salt to generate a key, and then use that as the key input to a secret box with a random nonce. There are other ways to do this, but unless you are well versed in cryptography, using NaCl is a smart choice since it is harder to misuse.

Related

return original value of sha256 [duplicate]

This question already has answers here:
How to decrypt a SHA-256 encrypted string?
(4 answers)
Closed 1 year ago.
I have a table called user in my database and I save the passwords in sha256. And I am wondering if I can now get the original value from the sha256, to display it on the user profile frontend.
Example
use sha2::{Digest, Sha256};
fn test() {
let password = "secret value";
let password_sh256 = Sha256::digest(password.as_bytes());
let encrypted_password = format!("{:x}", password_sh256);
println!("result: {:?}", encrypted_password);
// result: "c3a57afaa51d985ac0b4117f509e2ce6dd94d520e441778736a945b4cb941755"
}
Now how could you have the original value of the variable named password making use of the variable named encrypted_password?
I appreciate any help.
SHA-256 is designed to be computationally infeasible (in simpler terms: practically impossible) to invert like you want to do. In fact, it is provably the case that there are multiple inputs that hash to the same value (although it is also currently computationally infeasible to find them) so at best, you would be able to find some input that hashed to the same value. However, as mentioned, it is very unlikely that anyone can presently do so.
Additionally, there are some things to mention. First, you should never show the user their plaintext password. You don't know if the user is in a coffee shop, library, or other public place where others might be shoulder-surfing, so you wouldn't want to expose this. In addition, you don't want to be able to invert the password for security reasons (because that means anyone else can), so there's no way to actually show it.
Furthermore, you don't want to use plain SHA-256 for password hashing. The reason is that if people pick bad passwords, like “password123,” then all the users with the bad password will have the same password hash, and it's also easy to make a giant list of passwords that are known to be compromised and look them up in the list. What you want to do is use a password hashing function like Argon2 or bcrypt that (a) uses a unique salt (random data) for each password and (b) iterates the operation multiple times so that it's slow and guessing many passwords takes a long time. Fortunately, there are libraries in Rust for doing just this, and the argon2 crate has great documentation explaining how to do just this.

How to perform password reset in Node.Js app using hash?

I want to implement password reset in my Node.Js app using a very good advice from here https://stackoverflow.com/a/27580553/712347 where I would not have to record any tokens into my database.
Instead #airtonix suggested to use a hash function based on the user's login, email, password, timestamp, secret and salt.
What I don't understand is how do hash functions actually work — let's say I get a certain sequence from the data above — what would be the algorithm (and the library) to use to check if it was generated from the same data using a different salt?
Or am I misunderstanding the whole thing?
How do Hash functions generally actually work -
Hash Algorithms create a digital fingerprint of data usually called Digest or Hash. You primarily see Hash Algorithms used for comparison purposes rather than encryption.
Secure Hash Algorithms have some fundamental characteristics such as:
Non-reversible (one way function). You cannot determine the original set of data from the Digest.
The Digest will be a fixed size regardless of the original data's size.
Unique. Two different data sets cannot produce the same Digest.
What would be the algorithm and the library to use?
I would recommend SHA-2 (SHA-256 or SHA-512) as the hashing algorithm and utilize the Crypto module. It provides cryptographic functionality and a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions.
So lets say we have the following information (user.id, user.email, user.password, timestamp), concatenate it and pass it as the data parameter.
const hash = function hash(data){
// Returns a buffer containing raw bytes and converts to string
const salt = crypto.randomBytes(128).toString('base64')
// Creates and returns a Hmac object that uses the given algorithm
const hmac = crypto.createHmac('sha512', salt)
// Updates the Hmac object content with the given data
hmac.update(data)
// Calculates the digest of all of the data passed to be hashed
const digest = hmac.digest('hex')
return {
'salt' : salt,
'digest': digest
}
}
Running the above function with the same data but a different salt would result in a completely different Digest.

Keying Hashes/Login Security?

I am going to use hashing function, with salt:
$stored_pass = md5(md5($salt).md5($plain_pass)); **
/// I am wanting to know an efficient way to key/authenticate that hash.
I read up a bit about keying hashes, and MAC's, but didn't quite grasp HMAC's; so just figured that wrapping the hash in an encryption function, like aes, would work. ///
EG
$stored_pass = aes(md5(md5($salt).md5($plain_pass))); **
I would like to know the following:
Why key hashes for login? (Examples would be nice)
Methods for keying hashes? (Specifically for use in loign)
Disadvantages?
Are there still ways our hashing/password validation system could be more secure? (After we factor in hash, salted, keyed)
** What is the most "secure hashing algorithm?
" Secure by hardest to crack.
/// I read that sha-512 was one of the most secure; but then read contradicting articles stating, sha in any form should not be used, and something like bcrypt/scrypt should be used or PBKDF2. Then I read that bcrypt shouldn't be used, and has limitations. So I'm a bit confused. ///
When providing hash algorithms, I'd like to know the following:
What are the limitations of the hash algorithm?
Upsides?
Downsides?
/// My main concern is user security, so if that means less 'speed' I'm not bothered. In my eyes the login function's purpose is user security, so reducing the credibility of that security for a few milliseconds seems silly to me. (Just personal opinion). ///
Also I'd appreciate comments on my function:
$stored_pass = aes(md5(md5($salt).md5($plain_pass))); **
And any alternatives would be appreciated.
Note: I know some suggest using some sort of api for this, with functions already written, but that's not really what I'm looking for. I'd prefer to learn more about it myself.
I am going to use hashing function, with salt:
$stored_pass = md5(md5($salt).md5($plain_pass));
Don't use MD5. Learn how to safely store passwords instead. That page might very well answer all of your questions.
/// I am wanting to know an efficient way to key/authenticate that hash.
I read up a bit about keying hashes, and MAC's, but didn't quite grasp HMAC's; so just figured that wrapping the hash in an encryption function, like aes, would work. ///
MACs aren't the proper tool for the job here either, even if it seems tempting to use them. Maybe this primer on cryptography concepts will help illuminate the difference, but basically:
MAC - Provide tamper-resistance for a message.
Password hash - Slow, salted hashing algorithm.
They're totally different use-cases. (Although, PBKDF2 uses a MAC algorithm internally, so I can understand if you were confused by that.)
Encrypting a hash isn't what a MAC does, either. HMAC in particular is basically:
Hash your message (with a minor transformation).
Hash the key and output of step 1 (with another minor transformation).
/// I read that sha-512 was one of the most secure; but then read contradicting articles stating, sha in any form should not be used, and something like bcrypt/scrypt should be used or PBKDF2. Then I read that bcrypt shouldn't be used, and has limitations. So I'm a bit confused. ///
Easy answer:
Use password_hash() to create password hashes.
Use password_verify() to authenticate passwords against hashes.
Stop worrying about it.
The limitations of bcrypt (truncating after 72 characters OR the first NUL byte -- which are mentioned in the first article I linked to) aren't a practical concern, and rolling your own crypto is definitely less secure than using bcrypt.
If you are absolutely concerned about the bcrypt limitations, do this:
function bcrypt_sha384_hash($password, $cost = 10)
{
$fasthash = base64_encode(
hash('sha384', $password, true)
);
return password_hash($fasthash, PASSWORD_BCRYPT, ['cost' => $cost]);
}
function bcrypt_sha384_verify($password, $storedHash)
{
$fasthash = base64_encode(
hash('sha384', $password, true)
);
return password_verify($fasthash, $storedHash);
}

Letting Rfc2898DeriveBytes calculate the salt

I've read a lot of posting here about Rfc2898DeriveBytes() and it seems that in all of them, the salt is pre-calculated and passed to the constructor. However, there is a constructor that accepts a salt length input, and the salt will be calculated for you. It is available afterwards in the Salt property.
Any disadvantage to letting the method calc the salt? In my case, the usage is for password hashing.
Specifying the salt length instead of the salt itself may reduce the chance of choosing the salt insecurely when deriving a new key (or obscuring a password for storage). The salt should be chosen by a cryptographic random bit generator, and should be changed each time the password is updated. Presumably, this constructor will use a high-quality RNG that was properly seeded. Leaving that up the the application allows for mistakes at worst, and at best creates unnecessary complexity.
Of course, if you are recovering a key, for example to check user input against the stored password, you'd need to specify the salt that was used initially.

How safe is this procedure?

I'm going to use this kind of approach to store my password:
User enters password
Application salts password with random number
Then with salted password encrypt with some encryption algorithm randomly selected array of data (consisting from predefined table of chars/bytes)
for simplicity it can be used just table of digits, so in case of digits random array would be simply be long enough integer/biginteger.
Then I store in DB salt (modified value) and encrypted array
To check password validity:
Getting given password
Read salt from DB and calculate decrypt key
Try to decrypt encrypted array
If successfull (in mathematical mean) compare decrypted value byte by byte
does it contains only chars/bytes from known table. For instance is it integer/biginteger? If so - password counts as valid
What do you think about this procedure?
In a few words, it's a kind of alternative to using hash functions...
In this approach encryption algorithm is about to be used for calculation of non-inversible value.
EDIT
# Encrypt/decrypt function that works like this:
KEY=HASH(PASSWORD)
CYPHERTEXT = ENCRYPT(PLAINTEXT, KEY)
PLAINTEXT = DECRYPT(CYPHERTEXT, KEY)
# Encrypting the password when entered
KEY=HASH(PASSWORD)+SALT or HASH(PASSWORD+SALT)
ARRAY={A1, A2,... AI}
SOME_TABLE=RANDOM({ARRAY})
ENCRYPTED_TABLE = ENCRYPT(SOME_TABLE, KEY + SALT)
# Checking validity
DECRYPT(ENCRYPTED_TABLE, PASSWORD + SALT) == SOME_TABLE
if(SOME_TABLE contains only {ARRAY} elements) = VALID
else INVALID
From what you write I assume you want to do the following:
# You have some encryption function that works like this
CYPHERTEXT = ENCRYPT(PLAINTEXT, KEY)
PLAINTEXT = DECRYPT(CYPHERTEXT, KEY)
# Encrypting the password when entered
ENCRYPTED_TABLE = ENCRYPT(SOME_TABLE, PASSWORD + SALT)
# Checking validity
DECRYPT(ENCRYPTED_TABLE, PASSWORD + SALT) == SOME_TABLE
First off: No sane person would use such a homemade scheme in a production system. So if you were thinking about actually implementing this in the real world, please go back. Don't even try to write the code yourself, use a proven software library that implements widely accepted algorithms.
Now, if you want to think about it as a mental exercise, you could start off like this:
If you should assume that an attacker will know all the parts of the equation, except the actual password. The attacker, who wants to retrieve the password, will therefore already know the encrypted text, the plaintext AND part of the password.
The chance of success will depend on the actual encryption scheme, and maybe the chaining mode.
I'm not a cryptanalyst myself, but without thinking about it too much I have the feeling that there could be a number of angles of attack.
The proposed scheme is, at best, slightly less secure than simply storing the hash of the password and salt.
This is because the encryption step simply adds a small constant amount of time to checking if each hash value is correct; but at the same time it also introduces classes of equivalent hashes, since there are multiple possible permutations of ARRAY that will be recognised as valid.
You would have to brute force the encryption on every password every time someone logs in.
Read salt from DB and calculate decrypt key
This can't be done unless you know what the password is before hand.
Just salt (And multiple hash) the password.

Resources