Hashing and Salting confusion - encryption

I have read a lot about hashing and salting passwords. I know how hashing works, that is all very easy, but the thing I am confused about is salting.
If I hash and salt a password and stick it into the database, how can I check that password with the password given when a user tries to log-in. Surely because the salt is completely random, it will be near-impossible to get that salt again to be able to match the database
EXAMPLE:
//On create account.
hash(password + randomSalt) to the Database
//On log-in
hash(password + differentRandomSalt) compare to Database

You generate a random hash of a fixed length with every password you hash. Then you store that salt in combination with the computed hash into one database column.
When the user wants to login, you extract the salt-part from the database and can match the results.
Example:
var salt = GenerateSecureRandom(16) // generates e.g. 0x42552241
var saltedHash = Hash(salt + password)
Login scenario:
var saltedHash = GetSaltedHashFromDatabase()
var salt = GetFirstBytes(saltedHash) // 0x42552241
var hash = GetRemainingBytes(saltedHash) // 0x47111337
var match = IsMatch(hash, salt, userInput)
A database entry could look like this (where = is the salt and * is the hash):
0x4255224147111337
========********
For (much) more details have a look at: https://crackstation.net/hashing-security.htm

The salt is random for each different user/password combination. It's not random for the same user/password combination. If that would be the case, then you would not be able to verify the password, as you already found out. If a large enough salt is generated with a sufficiently secure random number generator then it would even be impossible to verify the password. The idea of the salt is to protect against rainbow table attacks as well as creating a different password hash for different users if the password is the same.
The salt is usually stored together with the username and password hash in the database. It could be made part of a special construct that contains the salt and the password hash or it could be stored in a separate column. Sometimes the password-hash is actually a special string containing both the salt and the hash in some kind of format (using hexadecimal or base64 encoding) that needs to be parsed, but it could also a binary value simply consisting of a statically sized salt and statically sized hash.
An example bcrypt string would be:
$2a$12$QyrjMQfjgGIb4ymtdKQXIewDBqhA3eNppF8qOrMhidnEbzNvmHqhy
which is constructed as in this SO answer.
Setup:
find user
receive & verify old + password (see below)
receive new password
generate random salt
calculate hash from password and salt
store salt & hash in database with user
Verification:
find user
receive password
retrieve salt & hash for user
calculate hash to verify from password and salt
compare and return result
Usually, for security reasons, you should try and do a time-constant compare, even if that's not really an issue for password hashing. Furthermore often no distinction is made between unknown user and wrong password, simply to avoid giving information to attackers.
It makes sense to construct your password hashing scheme in such a way that it allows for updates to the amount of iterations, hash size, hash function etc.

Related

Key verification in AES

If the user enters a wrong key for AES decryption, some garbage data is generated. I want to verify the given decryption key and throw an error if the key is incorrect. How can I verify the key entered by the user?
Use an HMAC. The basic premise is that you run the plaintext through an HMAC, add the result to the plaintext and then encrypt. Then do the opposite when decrypting. If the plaintext and HMAC result match, then you know you've got the correct key.
OR, if you want to know prior to decryption, use the key material provided by the user to derive two further keys (using, say PBKDF2). Use one for encryption and another for an HMAC. In this case, encrypt first and then apply the HMAC using the second key. This way you can compute the HMAC and check if it matches before you decrypt.
Simplest approach is to add a magic number to the plaintext file data in a predictable location before encrypting; when decrypting, if the magic number is wrong, you used the wrong key. Downside to this approach is that it cannot validate the integrity/authenticity of the entire message.
To do that, use AES in an authenticated mode (e.g. AES-GCM) which gives stronger guarantees that the rest of the message was not tampered with.
One common way used to verify if a key is correctly entered, without revealing the actual key, is by use of a KCV (Key Check Value). When you create the key you would at the same time calculate the KCV, when the key is then entered manually, you can verify the entry by re-calcuylating the KCV. This is eg. used when entering keys manually into HSM's from physical key letters.
To calculate a KCV for an AES key you encrypt an empty (0x00) block with the key and the first 3 bytes of the resulting encrypted block is then the KCV.
Take a look here

When deriving keys from passwords, should I store the key or use the key to encrypt?

The following quote has made me question what I thought I knew.
"Now consider bcrypt. It uses Blowfish to encrypt a magic string, using
a key "derived" from the password. Later, when a user enters a
password, the key is derived again, and if the ciphertext produced by
encrypting with that key matches the stored ciphertext, the user is
authenticated. The ciphertext is stored in the "password" table, but
the derived key is never stored."
I was under the assumption that you store the hash of the salted password.
Where:
- KDF = a key derivation function such as pbkdf2 or bcrypt
- salt = a unique 16 byte salt
- password = the password the user entered
- saltedPassword = the password appended to the salt
- hashedSaltedPassword = KDF(saltedPassword)
- USER = a database table where usernames and passwords are stored<br
USER.Password = hashedSaltedPassword
USER.PasswordSalt = salt
Is this correct or am I way off?
Your quote basically describes how to use bcrypt (which is a key-derivation function) as the basis of a salted hash function. That function's inputs are a password and a salt, and its output is a hash value. That hash value happens to be the ciphertext produced by encryping a constant string with a bcrypt-derived key, but you don't care about that: you're just using it as a hash value.
So yes, you do store the hash of the salted password.

How to auto generate password in sql database?

I am doing a mini project on bank account. Front end is ASP.NET and backend is SQL SERVER.
When a person creates an account, auto generated account number and password would be saved in the database and that account number and password would be sent to the email id of that user.
So that user can sign in with the provided account number and password.
So my question is how to auto generate that account number and password. I am not getting how to do that.
Hoping for the best. Thank You!
First off, allow them to create their own password and HASH that bugger. Don't email their password EVER. Email a link to reset if necessary, and expire the link shortly after sending.
Second, to generate an account number, I'd use a Guid
var accountNumber = new Guid.NewGuid();
In your database, you store the Hash version of the password, and upon login, you hash the login password and compare it against the database hash.
Also in the database, the Account number would be a UniqueIdentifier if you do choose to use a Guid.
Here is the most random way I can think of:
Select NewID() as UserName, NewID() as Password
Of course, your users aren't going to like this because it is really very long:
UserName Password
------------------------------------ ------------------------------------
F050EF1A-1D6C-4A20-991C-F6B034AEBD2E 86C8D5FC-D09E-45FF-9A4F-041239082C5E
So let's shorten it to 8 characters:
Select
SubString (Cast (NewID() as VarChar(50)), 1, 8) as UserName,
SubString (Cast (NewID() as VarChar(50)), 1, 8) as Password
This looks better:
UserName Password
-------- --------
63B1A547 D5566B8C
Since you want this to be generated when the row is saved, you probably have an INSERT statement that puts the account owner's information into the database. Modify that particular line of code to do this insert as well:
Insert Into AccountTable (UserName, Password)
Select
SubString (Cast (NewID() as VarChar(50)), 1, 8) as UserName,
SubString (Cast (NewID() as VarChar(50)), 1, 8) as Password
Of course.. since you know the account owners name, you can query back to get the owner. A much better idea is to have an identity column on the table, and use Scope_Identity to get the row you just inserted.

Is it possible to convert a 40-character SHA1 hash to a 20-character SHA1 hash?

My problem is a bit hairy, and I may be asking the wrong questions, so please bear with me...
I have a legacy MySQL database which stores the user passwords & salts for a membership system. Both of these values have been hashed using the Ruby framework - roughly like this:
hashedsalt =
Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--")
hashedpassword =
Digest::SHA1.hexdigest("#{hashedsalt}:#{password}")
So both values are stored as 40-character strings (varchar(40)) in MySQL.
Now I need to import all of these users into the ASP.NET membership framework for a new web site, which uses a SQL Server database. It is my understanding that the the way I have ASP.NET membership configured, the user passwords and salts are also stored in the membership database (in table aspnet_Membership) as SHA1 hashes, which are then Base64 encoded (see here for details) and stored as nvarchar(128) data.
But from the length of the Base64 encoded strings that are stored (28 characters) it seems that the SHA1 hashes that ASP.NET membership generates are only 20 characters long, rather than 40. From some other reading I have been doing I am thinking this has to do with the number of bits per character/character set/encoding or something related.
So is there some way to convert the 40-character SHA1 hashes to 20-character hashes which I can then transfer to the new ASP.NET membership data table? I'm pretty familiar with ASP.NET membership by now but I feel like I'm just missing this one piece. However, it may also be known that SHA1 in Ruby and SHA1 in .NET are incompatible, so I'm fighting a losing battle...
Thanks in advance for any insight.
The varchar representation in your Ruby app appears to be 'hex as string', something like this: 01AB02EF...23EF. that is, each byte is represented as a pair of characters that are the hex value of the byte, from 00 to FF. Therefore the SHA hash (20 bytes) is represented as 40 characters. IF the hash is the values (0, 1, 2, ...) the string will be 000102. The ASP base64 is the base64 encoding of the actual bytes. So all you need to do is take the MySQL characters and obtain the corresponding bytes, then encode them as base64.
You can actually do the transformation in SQL itself:
declare #x varchar(40);
set #x = '000102030405060708090A0B0C0D0E0F10111213';
declare #sql nvarchar(max);
set #sql = N'set #out=0x' + #x;
declare #out varbinary(20);
exec sp_executesql #sql, N'#out varbinary(20) output', #out output;
select #out for xml path('');
But to coerce your ASP.Net membership provider to use the salted hash your Ruby code created, irrelevant of the encoding used to store the hash digest, that's a whole different topic. You'll likely have to rewrite your own membership provider, at which point the storage encoding becomes irrelevant, since you can store them as you wish.
Ruby uses SHA2, and ASP.NET uses SHA1, and no, you can't 'convert' between those versions. For that you'd need to recalculate the hashes from the plaintext.
Edit: SHA is standarlized, so you can search in the internet for a SHA2 library to use in ASP.NET.

How to check case sensitive password in sql server08

In my application I am sending password to database,lets say my Password is PassworD123.
Now this is giving me proper value ,but when i am using password123..its also giving me the proper value.So how to chaeck for case sensitive data in SQL server.
Any demo code will help.
Thanks.
Why not use encryption to store the passwords in the database such as md5 because they will return different hashed versions for example
Md5 of password123 = 482c811da5d5b4bc6d497ffa98491e38
Md5 of PassworD123 = bbac8ba35cdef1b1e6c40f82ff8002ea
and when you compare them 2 they are clearly different.
I think you are using ASP therefore i dont know if it has an md5() function built in but php does have it. Another thing you should know is that if you are storing passwords in a database its better to store them using some sort of encryption that cannot be reversed
You can use COLLATE clause in your T-SQL statement.
Ex.
SELECT * FROM dbo.TableName WHERE Password = # password COLLATE SQL_Latin1_General_CP1_CS_AS
The immediate answer to your query is here:
http://web.archive.org/web/20080811231016/http://sqlserver2000.databases.aspfaq.com:80/how-can-i-make-my-sql-queries-case-sensitive.html
However I think your approach to storing / comparing passwords is a bit wrong. You should not be storing the password directly in the database. At-least MD5 it or something.
Well, the short answer is to use a case-sensitive collation - the longer answer is don't store plaintext passwords in your database!

Resources