Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypt/Decrypt a string based on a salt key

Tags:

php

I was wondering if it was possible to hold an encrypted text field within my database and have the ability to decrypt this piece of text based on a salt and authorized password?

For example:

$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 in the process of creating a completely encrypted/encoded database. Nothing will be plain text apart from the integer fields for the identifiers. Everything else will be encrypted/encoded.. Many will use a one way encryption, but some fields need to house a two way encryption type.

I cannot house non-encrypted text in the database. Everything needs to be encrypted before storing. But the approach to this is an unknown process to me. So I was wondering if I could get some assistance on where to start

like image 913
Sophie Mackeral Avatar asked Jun 06 '13 01:06

Sophie Mackeral


People also ask

Can you decrypt a hash with salt?

It is impossible to decrypt it. However, you may be able to crack it using the brute force method to find matching passwords in a dictionary. Best tool to use would be hashcat. Save this answer.

Can we decrypt SHA256 with salt?

Can we decrypt SHA256 with salt? Since SHA256 is a hash based on non-linear functions, there is no decryption method.

Is salt required for decryption?

it would require the salt to be stored. if the salt were lost/corrupted the user would not be able to decrypt the file anymore.


2 Answers

It sounds like you might want to do some more background on crypto generally, and DB encryption options specifically (you don't mention the data store, but there are MySQL and Postgres options for full encryption). In general, it is almost always a bad idea to "roll your own", and unfortunately, between mcrypt() and openssl_*() functions, there are frankly too many options presented to a novice (such as presenting EBC and CBC as equally valid options). While this thread: https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own is mainly talking about the futility of creating "novel" cryptographic primitives, the principle also applies to naive attempts at implementing application- and database-level encryption as well.

As a practical matter, the most challenging thing you will likely have to deal with is the issue of password/key management. The code below puts all of the responsibility on the client (sender) - and unless you save the submitted password (which sort of defeats the whole purpose), if the user forgets or is otherwise unable to supply their password in the future, encrypted data in the database will be unrecoverable. (And, yes, if you really want to go down the Yak Shaving path, there are options for multi-key envelope encryption).

If you store the key/password server-side you are, at best, only putting a small road bump in the path of an adversary: if she can manage to read your key file, she can retrieve the data. But worst, by saving the password locally, you are giving a false sense of security to your users, and if this is financial, health, or otherwise protected information, you and your organization take on that burden of that liability.

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 the code generator). For password hashing, take a close look at the phpPass library here: http://www.openwall.com/phpass/.

All that said, here is a working start for simple two-way, reasonably strong encryption, with randomly generated initialization vectors and salts, and a 256-bit AES symmetric (e.g., non-public key) cipher. Tested on OSX Lion & 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's 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 retrieve 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";

Sample output:

 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 
like image 101
PapaK Avatar answered Sep 18 '22 02:09

PapaK


Not a complete answer but an expansion of how salting works that was too long for a comment..

The salt shouldn't be treated as a string to be compared, it should be a part of the password that the end user doesn't have to type but is unique to that user. It's used to prevent a single compromised password breaching multiple accounts.

Eg let's say we've got a really simple system on which Bob has the password ABCDEF.

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

If an attacker gets access to the password list, they can only see the stored hash.

Of course, if Jane also uses the same password, her hash is going to be ED6522687 too - which means if you break into either account (through brute-force, social engineering, etc) you're going to get access to both accounts as you can see their hashes match.

Salting is where something is done to the password before hashing that's unique to each user and repeatable. Salt should be predictable so let's say Bob and Jane's salts are random numbers.

Now if you hash the password for bob ABCDEF123, you get a different hash to Jane's ABCDEF456.

Note that this isn't a complete explanation. Some other things to consider:

  • There's no such thing as a random number in this context, only cryptographically secure random numbers - and how random they are is complex, related to entropy and other fun stuff.
  • How quickly the hash is computed is a major factor with regards to hampering brute-forcing - hash algorithms like bcrypt are designed to be computationally expensive. unlike (say) SHA2
  • There's no reason for the user to submit (or even know) their salt.

Another observation which isn't usually emphasised enough... You should never trust anything you read on the internet about a topic like this - there are too many people who have incomplete understanding (I consider myself among them). So take this as reasons not to do it yourself, not a guide on how to do it.

like image 38
Basic Avatar answered Sep 20 '22 02:09

Basic