You are not afraid of getting your pants removed. Password security can be guaranteed in this way.
In the previous article "Designing the correct posture of a secure account system", I mainly proposed some design methods and ideas, but did not provide a more specific one, security encryption solution that can be implemented. After careful consideration and understanding of some of the current solutions, I have designed a secure encryption solution. This article mainly describes this solution. We are very welcome to discuss it with readers.
First, let's clarify the ultimate goal of the security encryption solution:
Even if the data is dragged to the database, the code is leaked, and the request is hijacked, the user's password is not leaked.
Specifically, our ideal absolute security system is like this:
First, it is difficult to drag data into the database. Even if the data is dragged to the database, attackers cannot crack the user's password. Even if the data is dragged to the database, attackers cannot forge login requests to pass verification. Even if the data is dragged to the database, attackers can hijack the user's request data and cannot crack the user's password.
How to ensure that data is not dragged to the database is not discussed here. First, we will talk about password encryption. Now, few systems will directly Save the user's password, at least it will calculate the md5 of the password and save it. The irreversible encryption method of md5 is theoretically safe, but with the appearance of the rainbow table, a large number of passwords with insufficient length can be pushed out from the rainbow table directly.
Therefore, md5 encryption is not enough. A clever programmer has come up with a solution. Even if a user's password is short, I only need to add a long character after his short password, and then calculate md5, it becomes very difficult to launch the original password. This long character is called Salt. The encrypted result is called Salt Hash. For example:
Salt
Previous we said, commonly used Hash function, SHA-256, SHA-512 will be more secure than md5, more difficult to crack, for higher security considerations, in my solution, will use SHA-512 instead of md5.
Salt
Through the salt hashing operation above, even if attackers get the final result, it is difficult to reverse the original password. No, but it can be pushed. If the attacker obtains the salt value, the attacker can enumerate simple passwords that traverse all six digits, add a salt hash, and calculate a result table, to crack a simple password. This is what we call brute-force cracking.
To cope with brute-force cracking, I used a slow hash of salt. Slow hashing means that executing this hash function is very slow. In this way, it takes a very long time for brute-force cracking to enumerate and traverse all possible results. For example, bcrypt is such a slow hash function:
Bcrypt
By adjusting the cost parameter, you can adjust the degree to which the function is slow. Assume that it takes 0.5 seconds for bcrypt to calculate a single password and traverse 6-bit passwords. The time required is (26*2 + 10) ^ 6)/2 seconds, about 900.
Well, with the above foundation, let's look at my final solution:
Password_secutity
There are a lot of details, I will talk about in stages:
1. Negotiate the key
Based on the asymmetric encryption key negotiation algorithm, both parties can negotiate a key that is only known to both parties when the communication content is completely disclosed, and then use the key for symmetric encryption to transmit data. Than the ECDH used in.
2. Request Salt
After both parties negotiate A key SharedKey, they can use the SharedKey as the AES symmetric encryption key for communication. The client sends it to the server's own public key A and the encrypted user ID (uid ). The server finds Salt1 and Salt2 for the uid from the database, and then encrypts the data and returns it to the client.
Note: The Salt1 and Salt2 stored on the server should be stored separately from the user data and stored in the database of other servers. This makes it very difficult to obtain Salt1 and salt2.
3. Verify the password
This is the most important step. After obtaining the Salt1 and Salt2, the client can calculate two salt hashing:
SaltHash1 = bcrypt(SHA512(password), uid + salt1, 10)SaltHash2 = SHA512(SaltHash1 + uid + salt2)
Use SaltHash2 as the AES key. The encryption includes uid, time, SaltHash1, RandKey, and other content transmitted to the server:
Ticket = AES(SaltHash2, uid + time + SaltHash1 + RandKey)AES(SharedKey, Ticket)
After the server uses the SharedKey to decrypt the Ticket, it finds SaltHash2 corresponding to the uid from the database, decrypts the Ticket, obtains SaltHash1, and recalculates SaltHash2 using SaltHash1 to check whether it is consistent with SaltHash2 in the database, to verify that the password is correct.
When two hash values are verified to be equal, a time-constant comparison function is used to prevent test attacks.
Time is used to record the time when data packets are sent to prevent recording playback attacks.
4. encrypted transmission
After the password is verified, the server generates a random temporary key TempKey (using a secure random function) and transmits it to the client using RandKey as the key. The data interaction between the two parties is encrypted using the TempKey as the AES key.
Assume that the database has been dragged
The above is the whole process of encrypted transmission and storage. Let's assume several attack scenarios:
If the data is dragged to the database, will the password be leaked?
Salt1, Salt2, and SaltHash2 in the database are exposed. It is almost impossible to reverse the original password from SaltHash2.
If the data is dragged to the database, can the attacker forge a login request to pass verification?
The attacker needs SaltHash1 when generating Ticket. However, because he does not know the password, he cannot calculate SaltHash1, and he cannot reverse push SaltHash1 from SaltHash2. Therefore, he cannot forge a login request to pass verification.
If the data is dragged to the database, attackers use man-in-the-middle attacks to hijack user requests. Will the password be leaked?
The man-in-the-middle has all the data on the Real Server and counterfeited the Real Server. Therefore, he can decrypt SaltHash1 in Ticket, but SaltHash1 cannot decrypt the original password. Therefore, the password will not be disclosed.
However, man-in-the-middle attacks can obtain the final TempKey to listen to all subsequent communication processes. This is a difficult problem to solve, because when everything on the Server is exposed, it is difficult for man-in-the-middle to assume that user data can be hijacked to impersonate real servers. The solution may only be to prevent man-in-the-middle attacks and prevent the public key of the Server from being tampered with on the client.
If the attack has reached this level, is there a way to remedy it? Yes. Because the attacker can only listen to the user's logon process and does not know the real password. Therefore, you only need to upgrade Salt2 on the server side to generate a new SaltHash2, which invalidates all attacks.
Specifically, the user can log on normally. After the server passes the verification, a new Salt2 is generated, and then SaltHash2 is re-computed and stored in the database according to the passed SaltHash1. The next time the user logs on again, the new Salt2 is obtained, and the password is not changed. The user can log on again, and the data that the attacker previously dragged to the database is also invalid.
Q &
Using the bcrypt slow hash function, the server can handle a large number of user login requests. Does the server have performance?
In this solution, we will note that bcrypt only performs computation on the client side, and the server side directly obtains the result of the client operation (SaltHash1) and then verifies the SHA-512 calculation result. Therefore, the performance pressure is distributed to various clients.
Why use two Salt values?
Two Salt values are used to prevent database theft, hijack user requests, and crack the password. Only users with a password can use the first Salt value to calculate SaltHash1, and the original password cannot be reversed. The second Salt value increases the difficulty of decrypting SaltHash1 directly after being dragged to the database.
Why do I need to dynamically request Salt1 and Salt2?
It is definitely not good to write the Salt value directly on the client, and you have to upgrade the client if you want to modify it. Dynamically request the Salt value and dynamically upgrade the password without upgrading the client: the server can change Salt2 regularly and recalculate SaltHash2, this quickly invalidates attackers even if they drag data once.
All databases have been dragged away. What is the significance of password leakage?
It actually makes sense. As mentioned in the remedy for upgrading Salt2, you can upgrade the account system without having to change the password. At the same time, it is also a responsibility to protect the passwords of users and prevent attackers from hitting the libraries of other websites.