Decoding a hash - php

I have some sensitive data in an online PHP application I am building. I want to store the data as a hash in the database, but that means I will have to decode the data every time I call it from the database. I know a hash is built to not be easily reversed engineered, so I would like to know what the best solution would be?
Unlike with passwords, I can't do a hash comparison - so how should I protect the information in the database?

What you're looking for is encryption, not hashing. Encryption is two way which means you can unencrypt to view the contents assuming you have the proper information for doing so (you do, snoopers don't).
See this post for code on how to do this with PHP.

Cryptographic hash functions are one-way functions, meaning that you cannot reverse them. What I presume you are looking for is encryption. You can use the Mcrypt or OpenSSL extensions to do this. My recommendation would be using AES with a 256-bit key (but remember that you need to keep the key secure) to encrypt the data before inserting it into the database and decrypting it upon retrieval. Now, you could use the methods provided by MySQL but I'd use Mcrypt myself. If you can provide the nature and approximate size of the data you are trying to keep secure I could recommend a suitable mode of operation.

Try reading this article on web cryptography: http://www.alistapart.com/articles/web-cryptography-salted-hash-and-other-tasty-dishes/
You can encode variables using the SHA-1 hash as follows:
sha1('password')
=> 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
MySQL supports data encryption and decryption. Ex:
INSERT INTO people (pet_name)
VALUES (AES_ENCRYPT('Schmoopie','my-secret-key'));
SELECT AES_DECRYPT(pet_name, 'my-secret-key') AS pet_name
FROM people;
Both of these examples are from the List Apart article.

Related

What is the best way to encrypt data without using the resource of mysql server ? Is mcrypt with CFB mode the best way with php?

I have a huge database with non encrypted fields.
These data are sensitive and the managers took a decision to encrypt them as soon as we can. And all new data should be automatically encrypted to the same way.
First Method:
If I use aes_encrypt to create a new field and insert the encrypted data to it like the following:
INSERT INTO myTable(name_en, name_es, phone)
VALUES(aes_encrypt(name_en, :key), aes_encrypt(name_es, :key), aes_encrypt(phone, :key))
And afterwards, each insert query should use aes_encrypt(), it will be resourceful to the server.
Second method:
Use libsodium library, which is a great solution to the new data. But the exisiting data will stay the same as libsodium couldn't be used inside a MySQL Query.
Third Method:
Using mcrypt_encrypt with MCRYPT_RIJNDAEL_128 as an equivalent to aes_encrypt, and then insert the encrypted variable into the query without letting MySQL do the encryption part, which will reduce loads and processing time.
But the mcrypt_encrypt isn't secure anymore, specially with the ECB mode.
What is the best method, to encrypt few fields in an exisiting MySQL database, and of course, the new one ? And if I used mcrypt with mode CFB, can use aes_decrypt afterwards to check the data ?
What is the best method, to encrypt few fields in an exisiting MySQL database, and of course, the new one ?
Write a PHP script that reads through your database and encrypts at the application layer (i.e. in PHP), not in the database layer (i.e. not in SQL). Encrypt them all at once, and have your scripts encrypt new fields opportunistically.
But the exisiting data will stay the same as libsodium couldn't be used inside a MySQL Query.
The fact that libsodium isn't available to MySQL shouldn't be a blocker at all. You don't want your database to ever have a chance to steal your keys, after all. MySQL should only see opaque ciphertext blobs.
You shouldn't be trying to encrypt with a SQL query. Do it outside of SQL and replace fields with ciphertext. Then when your process is complete, make sure you don't have plaintext cached anywhere.
Caveat
If you're trying to encrypt an entire database, you'll probably eventually want to use some of the fields in the WHERE clause of a SELECT query. Welcome to searchable symmetric encryption. There's a lot of crazy academic designs here (order-preserving encryption, homomorphic encryption, etc.).
For this use case, I recommend CipherSweet. It's fast, secure, easier to reason about, and doesn't require installing any third-party C extensions to use from PHP.

Encrypting data with PHP and MYSQL (SHA1, MD5, MCRYPT_RIHNDAEL_256)

I'm a little confused with the best practices of encoding data, I'm dealing with very sensitive data so need to do/learn the best method to protect the data:
I'm currenting hashing all Passwords with a combination of SHA1, MD5 and hashBCRYPT all of which use salt with a large mixed character keys.
All personal data I'm currently encrypting with PHP MCRYPT_RIJNDAEL_256
Is it worth me also adding AES_ENCRYPT so the the data is also encrypted with MYSQL? I have a read a few things saying PHP is the better method when you need to search and fetch data regularly.
Any help would be greatly appreciated!
You shouldn't be rolling your own hashing for passwords. Use PHP's built in password_hash() function: http://php.net/manual/en/function.password-hash.php
As for encrypting user information, you probably don't want to be rolling your own library either, there are many existing PHP libraries for encrypting that will save you from making mistakes, such as Defuse, PHPSecLib, PHPCrypt, etc.

128-bit PHP Encryption & Decryption of Data

I have a client who requires all of the data stored in the MySQL database to be encrypted with 128-bit encryption.
Assuming that before all data is inserted into the DB, a PHP function is run to encrypt it. Then, when I pull the data from the database, I run a decryption function to spit out the original text/info.
Can someone point in me in the right direction. I understand that the functions will use a shared/common key to encrypt and decrypt, but what makes it 128bit? Are there prebuilt functions in PHP that do this?
Appreciate any suggestions.
Scott
Typically, "128-bit encryption" refers to symmetric encryption using a 128-bit key. AES-128 is an excellent choice for an encryption algorithm.
You will also need to choose a mode of operation: CBC, CFB, OFB and CTR are all good choices if you only need privacy, but if you also want to protect the data against tampering, you should use an authenticated encryption mode such as EAX. Do not use ECB mode unless all your records are shorter than a single AES block (also 128 bits), and preferably not even if they are.
Depending on the mode you've chosen, you will typically also need to generate an initialization vector (IV) for each record, which should be a unique and unpredictable random cipher block (128 bits for AES). There are many ways to generate one, but two good ones (recommended by NIST) are either using the output of a cryptographically secure pseudorandom number generator or encrypting a unique ID in ECB mode (this is one of the rare cases for which it is OK to use). Depending on the crypto library you're using, it may take care of this for you. Please do note that, if you ever change the encrypted data in a record, you should always change the IV too.
As the other answers note, mcrypt is a good choice for a crypto library if you're using PHP.
I hope here is your solution. Refer two functions encrypt and decrypt on the page and grab the idea.
yes.You need to study about the classes/API using for encryption in which they must mentioned that.They are also dependent on algoritham that which type of algorithm you are using.Please follow this link to learn more about this.Here is a breif explaination about encryption.You can found a sample of code here but mycrypt is more recommended

How to implement 2 way encryption with either PHP or mySQL?

I am trying to securely store OAuth tokens and keys, and I know best practice is to encrypt these and treat them like user passwords. How can I do that while still being able to decrypt them and use them to make API calls to, say, twitter (I simply hash my passwords, which won't work for OAuth keys, as hashing is 1 way)?
I am open to doing it either in mySQL or PHP, so I would appreciate examples in either, or pros/cons of each approach.
You could use the mcrypt library in PHP (http://php.net/manual/en/book.mcrypt.php), it has support for all major cryptographic algorithms. I suggest you use AES-128, this is kind of the industry standard. Just make sure you store your key in a secure location. You can then encrypt your data, convert it to base64 and store that in your database. Whenever you need to use the data, just retrieve it from the database and apply the inverse operations.
I'm not familiar with how MySQL works exactly. Maybe there is a possibility to store data encrypted and have it store your key somewhere secure for you?
From a security point of view, the PHP method would be better though, because data going to and coming from your database is still encrypted.
Please don't use the XOR cypher, it is laughable at best. A single leaked plain-ciphertext pair will reveal your complete key (plaintext XOR ciphertext = key). This only provides perfect security when used as a one-time pad. Of course you can't use this, because now you have to use a different key for every piece of data and somehow have to securely store all those one-time pads. Maybe you could use some encryption for that ;) ...? (insert infinite loop here).

Storing Passwords in reversible form

I have a PHP app that needs to run bash scripts, and provide a username & password (for remote systems).
I need to store these credentials somewhere that is accessible by my PHP (web) app.
The logical place is the database (currently MySQL, but will be agnostic).
The problem with the "standard" way of hashing and storing the credentials, is that it is not reversible. I have to be able to get the credentials out as unencrypted clear text, to be able to insert the data into bash scripts.
Does anyone have any suggestions for a secure way to go about this ?
I thought maybe PKI'ing the credentials, and storing the result in the DB. Then use the private key to unencrypt (PHP can do that). Store the scripts to do this outside the web root.
Any thoughts much appreciated.
First, to state the (hopefully) obvious, if you can in any way at all avoid storing usernames and passwords do so; it's a big responsibility and if your credential store is breached it may provide access to many other places for the same users (due to password sharing).
Second, if you must store credentials prefer rather to stored passwords using a non-reversible, salted cryptographic hash, so if you data is compromised the passwords cannot easily be reverse-engineered and there's no need to store a decryption key at all.
If you must store decryptable credentials:
Choose a good encryption algorithm - AES-256, 3DES (dated), or a public key cipher (though I think that's unnecessary for this use). Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
Use a secure random generator to generate your keys. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
Store the encryption/decryption key(s) separately from your database, in an O/S secured file, accessible only to your applications runtime profile. That way, if your DB is breached (e.g. through SQL injection) your key is not automatically vulnerable, since that would require access to to the HDD in general. If your O/S supports file encryption tied to a profile, use it - it can only help and it's generally transparent (e.g. NTFS encryption).
If practical, store the keys themselves encrypted with a primary password. This usually means your app. will need that password keyed in at startup - it does no good to supply it in a parameter from a script since if your HDD is breached you must assume that both the key file and the script can be viewed.
For each credential set, store a salt (unencrypted) along with the encrypted data; this is used to "prime" the encryption cipher such that two identical passwords do not produce the same cipher text - since that gives away that the passwords are the same.
If the username is not necessary to locate the account record (which in your case it is not), encrypt both the username and password. If you encrypt both, encrypt them as one encryption run, e.g
userAndPass=(user+":"+pass);
encryptInit();
encrypt(salt);
encrypt(userAndPass);
cipherText=encryptFinal();
and store the singular blob, so that there is less occurrence of short cipher texts, which are easier to break, and the username further salts the password.
PS: I don't program in PHP so cannot comment on suitable crypto s/w in that environment.
You'll need to look into good 2 way cryptographic methods, and my general rule of thumb is:
If you implement your own cryptographic code you will fail.
So, find a good implementation that is well verified, and utilize that.
There is probably some good info here:
http://phpsec.org/library/
Check this library: PECL gnupg it provides you methods to interact with gnupg. You can easily encrypt and decrypt data, using safe public-key cryptographic algorithms.
I would suggest you not store the passwords, but use passwordless ssh connection from the host to the remote system by generating a ssh key and storing your public key in the remote system's authorized_keys file. Then you would only need to establish connectivity during configuration. Admittedly not quite answering your question, but storing passwords in a reversible form is a slippery slope to a security breach imho, although I am sure smarter brains than mine can make it safe.
One easy way to get started is to use mysql's ENCODE() and DECODE() functions. I don't know what algorithm is used underneath, but it's easy enough to use:
INSERT INTO tbl_passwords SET encoded_pw = ENCODE('r00t', 'my-salt-string');
and
SELECT DECODE(encoded_pw, 'my-salt-string') FROM tbl_passwords;
If you go the PKI, and I would, make sure you safe guard your private keys! The strong encryption provided by PKI is only as secure as your keys.
I think you're on target. Look at GPG for a good, open encryption library
It looks like you pretty much have two methods of doing this:
1) Like you suggested use an encryption algorithm or algorithms which can then be decrypted and used for authentication in your scripts. You can use the MCrypt library in PHP to accomplish this.
2) Depending on the required level of security and your script's level of vulnerability, you could use a secure hash, key, or some other hard to guess unique identifier that you can use to hijack each user's account within the confines of the script.
As many stated you scenario requires that you encrypt username and password. I would recommend that you check out the mcrypt extension of php for encryption/decryption.
I think I am going to investigate compiling a PHP script with the credentials embedded, on the fly, from the web app.
I would ask for the credentials (for a given use), then create and compile a new PHP script, for this use only. That way, the script will only do what I need, and should not be "readable". I think this sounds like the safest way to do this.
Will try using Roadsend. http://www.roadsend.com/
Just to follow up on the suggestion to use MySQL encode and decode functions, the manual is vague on just how these work:
The strength of the encryption is based on how good the random generator is. It should suffice for short strings.
But what I'd suggest is that you can instead use the built-in MySQL 5.0 AES functions; AES_ENCRYPT() and AES_DECRYPT()
SELECT AES_ENCRYPT('secret squirrel', '12345678') AS encoded
=> ØA;J×ÍfOU»] É8
SELECT AES_DECRYPT('ØA;J×ÍfOU»] É8', '12345678') AS decoded
=> secret squirrel
These use 128-bit AES which should be strong enough for most purposes. As others commented, using a salt value and a key with a high entropy is a good practice.
For PHP, it is important to note that AES encryption is implemented via MCRYPT_RIJNDAEL functions. Don't go paying for a non-open implementation when PHP has them available.
See the PHP page discussing available ciphers for more information.

Categories