Encryption / Decryption of a string based on a salt key

I was wondering if it is possible to store an encrypted text field in my database and be able to decrypt this piece of text based on salt and an authorized password?

For instance:

$Salt = $_POST['Salt']; $Password = $Query_Results['Password']; if ($salt == $Stored_Salt AND $Authorized_Password == $Password){ //Perform a decryption of the stored results echo $Decrypted_TextField; } 

I am creating a fully encrypted / encoded database. Nothing will be plain text except integer fields for identifiers. Everything else will be encrypted / encoded. Many will use one-way encryption, but some fields must contain a binary encryption type.

I cannot store plaintext in a database. Before storage, everything must be encrypted. But approaching this is an unknown process for me. So I was wondering if I could get help, where to start.

+6
source share
2 answers

It looks like you might want to make some more background on crypto in the general case and on the database encryption options (you did not mention the data store, but there are MySQL and Postgres options for full encryption). In general, it is almost always a bad idea to "collapse your own," and, unfortunately, between the mcrypt () and openssl _ * () functions there are frankly too many options presented to beginners (for example, the EBC and CBC views are equally valid parameters) . Although this thread: https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own- basically speaks of the futility of creating "new" cryptographic primitives, this principle also applies to naive attempts to implement the level application and database encryption as well.

As a practical matter, the most difficult task you will probably have to deal with is the problem of managing passwords / keys. The code below puts all responsibility on the client (sender) - and if you do not save the password provided (what kind of defeat of the target), if the user forgets or cannot provide his password in the future, the encrypted data in the database will not be recoverable. (And yes, if you really want to go down the Yak Shaving path, there are options for encryption using multiple keys).

If you store a server server with a key / password, you, at best, only put a small road track in the path of the enemy: if she manages to read your key file, she will be able to receive data. But worst of all, by storing the password locally, you give a false sense of security to your users, and if this is financial, medical, or other secure information, you and your organization take on this responsibility.

Finally, there is a mature library here: http://phpseclib.sourceforge.net/crypt/examples.html , but, in my opinion, it offers too many options for a novice user (see, for example, the default EBC mode in code generator). For password hashing, carefully check out the phpPass library here: http://www.openwall.com/phpass/ .

All that is said here is a working start for simple two-way reasonably reasonable encryption with random generated vectors and initialization salts and a 256-bit AES-symmetric (for example, non-public key) cipher. Tested on OSX Lion and CentOS / RedHat 6.

Good luck

 //$message = escapeshellarg( $_POST['message'] ); $message = 'This is my very secret data SSN# 009-68-1234'; // Set to some reasonable limit for DB. // Make sure to size DB column +60 chars $max_msg_size = 1000; $message = substr($message, 0, $max_msg_size); // User password (swap for actual form post) //$password = escapeshellarg( $_POST['password'] ); $password = 'opensesame'; // Salt to add entropy to users' supplied passwords // Make sure to add complexity/length requirements to users passwords! // Note: This does not need to be kept secret $salt = sha1(mt_rand()); // Initialization Vector, randomly generated and saved each time // Note: This does not need to be kept secret $iv = substr(sha1(mt_rand()), 0, 16); echo "\n Password: $password \n Message: $message \n Salt: $salt \n IV: $iv\n"; $encrypted = openssl_encrypt( "$message", 'aes-256-cbc', "$salt:$password", null, $iv ); $msg_bundle = "$salt:$iv:$encrypted"; echo " Encrypted bundle = $msg_bundle \n\n "; // Save it... (make sure to use bind variables/prepared statements!) /* db_write( "insert into sensitive_table encrypted_msg values (:msg_bundle)", $msg_bundle ); */ 

Now return it:

 // Retrieve from DB... //$password = escapeshellarg( $_POST['password'] ); $password = 'opensesame'; // Swap with actual db retrieval code here //$saved_bundle = db_read( "select encrypted_msg from sensitive_table" ); $saved_bundle = $msg_bundle; // Parse iv and encrypted string segments $components = explode( ':', $saved_bundle );; var_dump($components); $salt = $components[0]; $iv = $components[1]; $encrypted_msg = $components[2]; $decrypted_msg = openssl_decrypt( "$encrypted_msg", 'aes-256-cbc', "$salt:$password", null, $iv ); if ( $decrypted_msg === false ) { die("Unable to decrypt message! (check password) \n"); } $msg = substr( $decrypted_msg, 41 ); echo "\n Decrypted message: $decrypted_msg \n"; 

Output Example:

  Password: opensesame Message: This is my very secret data SSN# 009-68-1234 Salt: 3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37 IV: 00c1d3b4c6a6f4c3 Encrypted bundle = 3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37:00c1d3b4c6a6f4c3:KB6k+GlM+0EHbETUgEe8Lck0nF5qBz+51wc5LtmS4XMOm0Pfyyr2PIXMVEyzs/41 array(3) { [0]=> string(40) "3f12ce187d5c5bcc3b0d5acf1e76fad8b684ff37" [1]=> string(16) "00c1d3b4c6a6f4c3" [2]=> string(64) "KB6k+GlM+0EHbETUgEe8Lck0nF5qBz+51wc5LtmS4XMOm0Pfyyr2PIXMVEyzs/41" } Decrypted message: This is my very secret data SSN# 009-68-1234 
+7
source

Not a complete answer, but an extension of how pickles work that were too long for comment.

Salt should not be considered as a string for comparison, it should be part of a password that the end user should not print, but unique to this user. It was used to prevent multiple accounts from cracking a single compromised password at the same time.

For example, let's say we have a really simple system on which Bob has an ABCDEF password.

Passing ABCDEF through our hash algorithm results in (say) ED6522687

If an attacker gains access to a list of passwords, he can only see the saved hash.

Of course, if Jane also uses the same password, her hash will also be ED6522687 - this means that if you go to any account (through brute force, social engineering, etc.), you will get access to both accounts, since you can see that their hashes match.

Salting is what was once done with a password before hashing, unique to each user and repeatable. The salt should be predictable, so let me say that the salts of Bob and Jane are random numbers.

Now, if you have a password for bob ABCDEF123 , you get another Jane hash ABCDEF456 .

Please note that this is not a complete explanation. Some other things to consider:

  • In this context, there is no such thing as a random number, only cryptographically safe random numbers - and how random they are, complex, associated with entropy and other funny things.
  • How quickly a hash is calculated is a major deterrent to coarse-force algorithms β€” hash algorithms such as bcrypt are designed for expensive computations. unlike (say) SHA2
  • There is no reason for the user to send (or even know) their salt.

Another remark, which is usually not sufficiently emphasized ... You should never trust anything you read on the Internet about such a topic - there are too many people who have an incomplete understanding (I consider myself among them). Therefore, take it as a reason not to do it yourself, and not a guide on how to do it.

+2
source

Source: https://habr.com/ru/post/946630/


All Articles