Encryption: Testing that a string is properly decrypted? - php

Here's a theoretical one that not only applies to PHP, but probably to more languages.
Let's say that I encrypt a string with the mcrypt library using and the AES-256 cipher. The string, encrypted, would now look similar to þøÆ{”ò(ü´îÚÜÇW¹ËŸK­¯L‘rø?ª¶!JF£­º+Œ’Ú'‚.
If the encryption key would change between the events of decryption and encryption, the result of the decryption would obviously be worthless.
Since an encrypted string contains, at least to me, random chars, It wouldn't be easy to run some sort of test on it to ensure that it is in encrypted/decrypted state.
I've spent some time thinking. How can I test that a string has been properly decrypted?
What if I appended a small prefix to the original string before encrypting it in the first place, and then removed this prefix upon decryption. If this prefix wasn't found, it would be safe to say that the decryption has failed.
Would this be an appropriate way to handle this?

To test data integrity you want a Message Authentication Code (MAC).
There are a few stand-alone MAC algorithms, which look like a hash function with a key. The very standard MAC algorithm is HMAC (which uses a hash function).
Since you also encrypt the data, you will want to use an encryption mode with a builtin MAC; there are a few such modes, such as GCM or EAX. Those modes apply to a block cipher, usually the AES.
Adding a known prefix or suffix to the data before encryption is a homemade MAC. MACs are subtle and error prone. For instance, if you add a CRC32 and then encrypt with a stream cipher (or a block cipher in CTR mode), then you are reproducing one of the seven capital sins of WEP (see section 4 in particular, for the CRC32-as-MAC issue). Basically your integrity check is no longer resistant to active attacks; you are only detecting innocent mistakes, such as using the wrong key.
(Unfortunately, it seems that MCrypt does not support any combined encryption/MAC mode. PHP itself, when compiled with the --with-mhash option, provides the mhash() function which implements both raw hashing, and HMAC.)

How can I test that a string has been properly decrypted?
The "small prefix" idea should be fine; also the excellent idea by #CodeInChaos. Other than that, storing the string in some defined format (like serialize() or json_encode()) and failing to restore it (unserialize(), json_decode()) would be indication of a broken decryption as well.

Related

openssl_encrypt(... string $method ...) Syntax

I couldn't find this information anywhere on here or on Google, so quick question: When using openssl_encrypt should I be using the actual cipher names (i.e. "bf-cbc") or can I use the aliases (i.e. "blowfish")?
FWIW, I'm using PHP 5.6.34.
Bonus question: According to the PHP documentation, some of the methods have been proven to be weak, so which one is the strongest or which are the strongest amongst the methods that remain?
Don't use the aliases, be as specific as you can with the cipher you intend to use.
AES is probably the most appropriate algorithm to use here. The mode you use is important as well. With this in mind, I would prioritize the following, in order:
aes-*-gcm
aes-*-ctr
aes-*-cbc
Where * is obviously one of 256/192/128. Remember that each of the above modes has different requirements for it to be secure. GCM needs a 96-bit nonce, and no additional authentication. CTR usually uses a 128-bit nonce and needs a MAC to be secure. Using the same nonce and key for two different messages in GCM or CTR mode will expose the plaintext, so don't ever do that. CBC needs a 128-bit IV and a MAC to be secure.
I suggest you view the code in this repository for an example of secure encryption in PHP.

PHP Two Way Encryption With Checksum

I am trying to pass a JSON string from one web application to another using URL parameters (for an internal SSO server).
What I need to do is be able to encrypt the JSON string (which is a user payload object) with a pre-shared key, forward the user to the service provider application with the payload attached as a URL parameter and then on the service provider application decrypt the payload back into a JSON string to get the required information.
Now this part isn't as much of an issue thanks to all of PHP's built in encryption functions but the next part is the difficulty. I am needing to embed a checksum within the encrypted string which can be checked when decrypting it so that if it has been modified in transit then I can raise an exception.
The purpose of this is to make sure that the user payload has not been modified in transit either accidentally or deliberately.
You want to provide more than a "checksum" (usually defined as "calculable by any party"); you want to provide an authentication tag or message authentication code (MAC). You have a couple options:
Use an "authenticated encryption" (AE) or "authenticated encryption with associated data" (AEAD) cipher to do this. AE(AD) ciphers provide an "authentication tag" over the cipher text, either in a single pass or with a repeated process over the encrypted cipher text. Examples (probably available in whichever PHP cipher library you're using) are GCM, EAX, and CCM. This is recommended, as the decryption operation will fail if the authentication tag is not verified, and only one shared secret (key) is necessary.
You can construct the system yourself using cryptographic primitives. This is less ideal, as you are responsible for more independent pieces, you need to manage more keys (if you have access to an OMAC implementation, you can use the same key), and your individual construction is not vetted by third parties (aka the collective work of the internet). If you follow this path, you need to keep some key details in mind:
Use a strong hash-based message authentication code (HMAC) such as HMAC/SHA-256, -384, or -512. Do not use SHA-1 or MD5, as these are easily brute forced.
Verify the HMAC before decrypting the cipher text. Any HMAC that fails means the entire cipher text should be discarded. You can remember this (on the generating side) as Encrypt Then MAC, and if you search for it, you'll see that not following this advice is the source of many cryptographic vulnerabilities and implementation exploits.
Verify the HMAC with a constant-time algorithm (i.e. do not use a short-circuit string equality comparison, the default in Java). PHP provides hash_equals to do this. Here's a quick explanation of timing attacks and a code review of a PHP example.
For either choice you'll want to encode the resulting cipher text and authentication tag with URL-safe Base64 in order to avoid data loss or corruption. If your message format is not strictly structured with included lengths, you'll have to pre-share the protocol ahead of time (i.e. for message m of length n bytes -> 16 bytes IV | n-48 bytes cipher text | 32 bytes HMAC).
Last note: always use a unique, non-predictable IV for each message that is encrypted with a key. Many people gloss over this, because it's "easy to just use 0x00 * 16", but any stream cipher mode of operation like CTR used as the foundation of GCM and CCM will lose fundamental security if two messages are encrypted with the same IV and key.

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

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