128-bit PHP Encryption & Decryption of Data - php

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

Related

Decoding a hash

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.

High performance encrypt/decrypt in both PHP AND MySQL

Id like to redesign some aspects of my database/website, and am looking for reasonably strong crypto functions in PHP, which are also supported by MySQL.
I also need the encrypt/decrypt to be 100% portable & compatible
Mostly I will be crypting in PHP, selecting the crypted version from MySQL, and then decrypting in PHP.
But occasionally I will need to run a query which decrypts the field in MySQL, for reporting purposes etc
I had a look at mycrypt php library, but its not clear which of these ciphers are supported by MySQL.
Any recommendations plase?
After a bit of Google-fu it appears MySQL uses 128-bit AES with Electronic Codebook (ECB) mode. For the key, you'll need to use exactly value that's exactly 16 bytes.
Lets say I use _My-16-byte-key_ as my secret key.
SELECT AES_ENCRYPT('The rooster crows at midnight!', '_My-16-byte-key_')
Result is: 7e41520667dc20457db2f18644bad06dd62a2120be8b93cd5596d8ffea45ef0f
Over in PHP, I can use mcrypt_decrypt to reverse it:
$secret = '7e41520667dc20457db2f18644bad06dd62a2120be8b93cd5596d8ffea45ef0f';
$key = '_My-16-byte-key_';
print mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, pack('H*', $secret), 'ecb');
Result:
The rooster crows at midnight!
I'll leave the reverse flow as an exercise to the reader. =)
Here: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html
Is a list of all the encryption functions in MySQL.
I recommend to use AES.
All the other encryption options are no longer secure.
AES supports a 128 bit key length (and a 256 bit key length with a recompile of the MYSQL source).
Don't forget to salt everything you encrypt with AES to prevent rainbow table attacks.
If you use the same key to encrypt decrypt everything all the attacker needs to do is get that key, with the hash function (and salt) you don't have to worry about losing the key, with this option you run a huge risk of losing the key and all your passwords with it.
Use a hash function instead: SHA256 with a salt.
I also recommend AES, it is designed to be fast and since it is industry standard it is strong enough. However, what the reason to encrypt data inside database? If your encryption key will be stored in PHP scripts, it will not be more secure than using cleartext records. It has benefits only if many scripts access the same database.

Encryption: Use of initialization vector vs key?

I am using PHP's mcrypt library and the AES-256 (rijndael) algorithm, which requires both a key + initialization vector to run.
My logical brainside isn't really going along with this. Isn't just one key enough?
Theoretical scenario:
If I had encrypted sensitive data stored in a database, which only the owner should be able to decrypt, would it be appropriate to use the users hashed password to either the key or the initialization vector to his or her data?
Should the key be considered more private than the initialization vector or is it the other way around?
No, in fact an IV is vital in most implementations. The IV is also considered to be safe for public use, for instance the IV is transmitted in plain text for WEP and WPA1/WPA2. The problem arises when this same key+iv is used to encrypt the same plain text. The cipher texts will be identical, unless you use an IV. If an attacker can encrypt arbitrary plain text with this key, and then view the cipher text. This is a much faster way of brute forcing other cipher text that the attacker has obtained.
Not only that, the IV must be random or you would be in violation of CWE-329. The reason why this is a problem is a bit more subtle and I didn't get it at first. You didn't mention this, but i hope you are using either the CBC or CMAC modes
The use of a hash function on a password is nearly identical to using a String2Key function. This is a solid design so long as an attacker can't use SQL Injection to obtain the key.
Initialization Vector (IV) is not a key at all, and is not secret. In fact, it is often exposed (e.g. prepended to the encrypted data). It is used as an additional random input to the encryption algorithm so that the result of encrypting the same clear data is different each time you use a different IV. This way, statistics cannot be gathered on the encrypted data. It does not "improve" the encryption strength by itself.
You can look here for nice diagrams showing how and why IV is used.
Do not use hashed password as a single source for key and IV. As a rule of thumb, you should generate random IV EVERY TIME you update encrypted data and store IV with this data. Key can be reused multiple times, but use salted hashing and store salt with data too.
If you just hash user passwords and use it as encryption keys, users with same passwords will have same keys. Depending on your database structure and intruder access rights there could be some unfortunate cases when users with same passwords can be detected. Add at least unique username to this hash.
If you do not change IV for every data update, information about data changes can be leaked. With CBC or CFB mode identical first plaintext blocks will be encrypted to identical ciphertext until first plaintext change, so position of this change can be determined.
If you're using the EBP mode of the block cipher, or most of the stream ciphers, identical key+IV combinations on different plaintexts will offer the attackers a direct view on the XOR result of the key. This by extension reveals the key itself and to some extent the password.
But do I mean IVs are definitely necessary? No. As long as you change your password each and every time on your next plaintext block(even the same block the second time), you're completely fine without IVs. In fact, all that an IV does is the automation of the above process.

What is, if any, prefered mcrypt cipher for encrypting/decrypting php objects or arrays

I'll keep this short and simple. As part of PHP's mcrypt library there are 40 or so possible ciphers, see here.
Not knowing much about encryption myself, I'm working under the assumption regardless of the cipher used, the data when decrypted is identical as the data encrypted (otherwise what's the point right?)
I need to encrypt and then decryption either an array or serialised standard object. I've browsed a couple examples online of the basic implementation of the mcrypt library and noticed that each example used a different cipher. It got me wondering if there was any significance to this, or simply personal preference?
My question is, is there any significant differences between these ciphers I should be concerned with knowing that
I'll be encrypting/decrypting is an either an array or serialised standard object, and contain relatively little data.
This operation will be fairly uncommon so speed isn't a massive issue, anywhere in the range on < 2s is acceptable.
The encrypted string will need to be stored in a cookie and transmitted via url query string (so there are limitations on length and character set)
Note
I'm not after a debate about whether I should be using a hash or hmac. Encryption is necessary and the correct option for this problem.
Any reasonable cipher encrypts/decrypts between plaintext/ciphertext given the correct key.
There are huge differences to which cipher you choose. Be it block length, key length and/or general security. For instance, you should never use DES because it only uses a 56-bit key. Similar for other ciphers on the list you refer to. Before using any cipher always read up on it and determine whether it is a good cipher for your context.
But I can't go into detail about every cipher on your list here. :-)
I personally like AES (Rijndael) which takes three sizes of keys 128, 192 and 256 bits. The best known attack is faster than a brute-force attack but is still infeasible. It is fast, too (actually Intel included machine instructions for AES in Westmere and Sandy Bridge).
Serpent and Twofish are also good ciphers. Serpent came second to Rijndael and Twofish came third (I think it was) in the AES contest some years back.

What is the best way to encrypt a very short string in PHP?

I would like to encrypt strings which could potentially only be about three or four characters but run to about twenty characters. A hashing function (md5, sha1, crypt etc) is not suitable as I would like to be able to decrypt the information as well. The mcrypt extension has a thoroughly daunting array of possibilities.
Does anyone have any ideas about the best way to safely encrypt short strings and why? Does anyone have any links to any material introducing a casual programmer to practical encryption scenarios?
I like to use GnuPG for anything that needs to be encrypted on a server and then possibly decrypted either on the server or on another server (which is usually my case). This allows for an extra level of security since in my scenario the encrypting server doesn't have the key to decrypt the data. It also allows for easier manual decryption. There are a few good wrappers available for various languages (another advantage), one for PHP is GnuPGP PHP Class.
mcrypt is linked into most builds of PHP by default. It contains all the primitives you're likely to need. Without knowing more about what you're encrypting, what your threat model is, etc, it's hard to give concrete recommendations on what algorithm, mode of operation, etc to use.
One thing I can say for certain: With short text strings, it's more vital than ever that you MUST use a unique, random Initialization Vector. Otherwise, it's trivial for someone to mount a variety of attacks against the encrypted data.
I highly recommend the suggestions of Chris Kite. Without knowing more about what you're doing, why, and the threats you anticipate needing to protect against AES-128 is likely sufficient. The ability to use symmetric encryption is great for a standalone app that will be both the decryptor and encryptor of data. As both Chris Kite and Arachnid said, due to the small size of your data it's advised that you pad the data and use a random Initialization Vector.
Update: As for why.... if the data is small enough, and the IV can be predicted, it's possible to brute force the plain-text by generating cipher-text for every combination of plain-text with the known IV and matching it up to the captured cipher-text. In short, this is how rainbow tables work.
Now if you're going to encrypt on one server and decrypt on another I'd go with the suggestions of pdavis. By using an asymmetric method you're able to separate the encryption keys from the decryption keys. This way if the server that encrypts data is compromised, the attacker is still unable to decrypt the data.
If you're able to, it'd help the community to know more about your use case for the encryption. As I mentioned above, having a proper understanding of plausible threats is key when evaluating security controls.
I agree with Chris Kite - just use AES 128, this is far sufficient.
I don't know exactly your environment, but I guess you're transmitting the data somehow through the internet.
Don't use ECB, this will always produce the same result for the same plain text.
CBC mode is the way to go and don't forget a random initialization vector. This vector has to be communicated with the cipher text and can be sent in the clear.
Regarding your data, since AES is a block cipher, the outcome is always a multiple of the block size. If you don't want to let the observer know if your data is short or long, add some padding to extend it up to the maximum expected size.
If you want to encrypt and decrypt data within an application, you most likely want to use a symmetric key cipher. AES, which is the symmetric block encryption algorithm certified by the NSA for securing top secret data, is your best choice. There is a pure-PHP implementation available at www.phpaes.com
For your use it sounds like AES128 is sufficient. You will want to use CBC mode with a random initialization vector, or else the same data will always produce the same ciphertext.
Choosing the right encryption algorithm is a good first step, but there are many factors to a secure system which are hard to get right, such as key management. There are good resources out there, such as Applied Cryptography by Bruce Schneier, and Security Engineering by Ross Anderson (available for free online).
Does it matter if anybody can decrypt it? If you're just trying to obfuscate it a little, use ROT13. It's old school.
Any one-way encryption algorithm such as Blowfish will do, I guess. Blowfish is fast and open. You can use Blowfish through the crypt() function. AFAIK there are no encryption algorithm that work especially well on small strings. One thing to be aware of though is that brute-forcing such small strings will be very easy. Maybe you should encrypt the string along with a 'secret' salt value for additional security.
You can use the general programming ideas without relying in built in encryption/decription functions Example create a function call it
function encryptstring($string) {
$string_length=strlen($string);
$encrychars="";
/**
*For each character of the given string generate the code
*/
for ($position = 0;$position<$string_length;$position++){
$key = (($string_length+$position)+1);
$key = (255+$key) % 255;
$get_char_to_be_encrypted = SUBSTR($string, $position, 1);
$ascii_char = ORD($get_char_to_be_encrypted);
$xored_char = $ascii_char ^ $key; //xor operation
$encrypted_char = CHR($xored_char);
$encrychars .= $encrypted_char;
}
/**
*Return the encrypted/decrypted string
*/
return $encrychars;
}
On the page with link to include the id's required to be encrypted
/**
*While passing the unique value to a link
*Do the following steps
*/
$id=57;//or if you are fetching it automatically just pass it here
/**
*For more security multiply some value
*You can set the multiplication value in config file
*/
$passstring=$id*346244;
$encrypted_string=encryptstring($passstring);
$param=urlencode($encrypted_string);
/**
*Derive the url for the link
*/
echo 'something' ;
On the target file that get opened after the link is clicked
/**
*Retriving the value in the target file
*Do the following steps
*/
$fetchid=$_GET['aZ98#9A_KL'];
$passstring=urldecode(stripslashes($fetchid));
$decrypted_string= encryptstring($passstring);
/**
*Divide the decrypted value with the same value we used for the multiplication
*/
$actual_id= $decrypted_string/346244;

Categories