How to verify that the decryption result is correct? - php

I've been playing around with php mcrypt over the weekend with AES used to encrypt text strings with a key. Later I worked up a tiny php tool to encrypt / decrypt your strings with AES/mcrypt now when the key is "wrong" and the text doesn't get decrypted, you end up with what I think is binary from what I've read around (http://i.imgur.com/jF8cZMZ.png), is there anyway in PHP to check if the variable holds binary or a properly decoded string?
My apologies if the title and the intro are a bit misleading.

When you encrypt text and then try to decrypt it, you will get the same text, but when you try to decrypt random data, there is a small chance that the result will be text (decreasing with length of data). You haven't specified what kind of data we are talking about, but determining if the decryption is successful by applying a heuristic is a bad idea. It is slow and may lead to false positives.
You should have a checksum or something like that to determine if the decrypted result is valid. This could be easily done by running sha1 on the plaintext data, prepend the result to the text and encrypt it as a whole. When you decrypt it, you can split (sha1 output has a fixed size, so you know where to split) the resulting string run sha1 on the text part and compare with the hash part. If it matches you have a valid result. You can of course improve the security a little by using SHA-256 or SHA-512.
That's is just one way of doing it, but might not be the best. Better ways would be to use an authenticated mode of operation for AES like GCM or CCM, or use encrypt-then-MAC with a good MAC function like HMAC-SHA512.
With using the approaches above you're free to use any kind of data to encrypt, because you're not limited to determining if it is text or not anymore.

Related

Low level encryption in php for basic, non-personal data

I have a php page which print different options to the client:
foreach($strings as $i => $string){
echo 'Go with option '.$i.'';
}
I want that the user can retrive the content of $string only on my webpage and cannot by sniffing html code or something like that. The string length is not long, less than 100 chars, and it's dynamic. I would like the url to be "elegant". I tried using
$string = gzencode($string);
$string = urlencode($string);
But it becomes a monster of string. Is there any basic function to encrypt the string? The other idea would be setting an array in $_SESSION, but that would make my urls not shareable. Creating a database is a mess. I need something very easy, just like old roman encryption method. Just not that because is a little bit too easy.
It is not possible to give a good advise without knowing your use-case and how much you know. But I like thought experiments like this, so here are some ideas for you to think about.
Encryption and encoding is not the same, so you first need to decide if you want to obfuscate or secure the data. Encoding obfuscate the data making it harder for non-tech people to read it, encryption make it really hard to read it.
If you want to obfuscate php have the function http://php.net/manual/en/function.str-rot13.php, but since this is like old roman "encryption" you could base64 encode it after. This will give you a string that is obfuscated and not readable by most users, but most here on SO will recognize what it is and be able to read it.
Another way to obfuscate the data could be to xor the string with another string.
You did include that you are not ready to include a database, but maybe you could implement a simple replacement with storing a lookup-table in a file. Using the key in the link and then looking up the value in the file.
If you want to actually encrypt the data you should look into openssl_encrypt and openssl_decrypt and encrypt it with a key using cbc mode, this is the way to go if you want security.

Unique encrypted values for same string

While using Laravel, I recently noted that when it encrypts a value the encrypted string keeps changing.
For example
ecrypt('abc') returns xyzABCDXZY
But if I run the same function a little while later:
ecrypt('abc') returns xyzABDJSAS
Now this has me really really confused. If the encryption result is different for each time the function is called how on earth are they able to get back the original value (abc in this case) upon calling the decrypt function?
I suppose it has something to do with the encryption function but I can't for the life of me figure out what and how. Can someone shed some light on this? Thanks.
in fact it may be able to decrypt it, for example, the encryption algorithm can embed a variable in the encrypted data besides the plain text which was encrypted ( like a seed value ) and so the algorithm would
1) encryption: generate a seed, use that seed to cipher the data, hide the seed inside the ciphered data ,produce the final ciphered data
2) decryption: read the encrypted data, get the hidden seed and apply this to get the plain text
in all cases, the plain text data would be the same.

Test if a string has been encrypted using mcrypt_encode in php?

Is there a way in PHP to test if a string has been encrypted using mcrypt_encrypt?
You have not written what you're actually concerned about specifically, but:
Whether or not some data has been encrypted is not dependent on which encryption function has been used but which encryption algorithm. Say, if somebody has encrypted something in PERL or in PHP - you can't tell by having the encrypted string.
So as this applies, you can't tell for mcrypt_encrypt. That function does not leave any sign inside the encrypted data.
However, if you have the key and the original text (plain) as well as the algorithm, you can reverse what mcrypt_encrypt does with mcrypt_decrypt. You can then compare the plains and if they match you can say that the plain was encrypted with the specific key and algorithm.
As we're talking about encryption, this is normally not the case, you don't have the plain.
However, you can create a checksum of the plain and encrypt it as well. Then you can decrypt it later on and compare it with a checksum of the plain you encrypted as well to tell if the data was successfully decrypted. But as this shows, this is actually additional information next to the encrypted data.
If you add more information what you're looking for, it might be possible to give more helpful suggestions.
when encrypting add some static text to your string ; when cheking use mcrypt_encode again with static text this time without original string see if encrypted static text exist in encrypted string . it should work
Presumably you mean mcrypt_encrypt()? There is no mcrypt_encode() function.
No. A properly encrypted string should be indistinguishable from random garbage. The only way to test a crypted string to see if it's crypted is to decrypt it.

What's a good hash to use between PHP and Python?

I have the luxury of starting from scratch, so I'm wondering what would be a good hash to use between PHP and Python.
I just need to be able to generate the same hash from the same text in each language.
From what I read, PHP's md5() isn't going to work nicely.
md5() always plays nicely - it always does the same thing because it is a standard hashing format.
The only tripping hazard is that some languages default return format for an MD5 hash is a 32 byte ascii string containing hexadecimal characters, and some use a 16 byte string containing a literal binary representation of the hash.
PHP's md5() by default returns a 32-byte string, but if you pass true to the second argument, it will return the 16 byte form instead. So as long as you know which version your other language uses (in you case Python), you just need to make sure that you get the correct format from PHP.
You may be better using the 32-byte form anyway, depending on how your applications communicate. If you use a communication protocol based on plain-text (such as HTTP) it is usually safer to use plain-text versions of anything - binary, in this case, is smaller, but liable to get corrupted in transmission by badly written servers/clients.
The binary vs. ascii problem applys to just about any hashing algorithm you can think of.
What is it you want from the hash? (portability, security, performance....)
From what I read, PHP's md5() isn't going to work nicely.
What did you read? Why won't it work?
I just need to be able to generate the same hash from the same text in each language
Since PHP only provides crc32 (very insecure), md5 and sha1 out of the box, it's not exactly a huge amount of testing you need to do. Of course if portability is not an issue then there's the mcrypt and openssl apis available. And more recently the hash PECL gives you a huge choice.
I suggest to use sha1 as it is implemented out of the box in both but has no collision valnurabilities like md5. See: http://en.wikipedia.org/wiki/MD5#Collision_vulnerabilities

Encrypting / Decrypting, passing variables values

I am encrypting values of variables that I am sending through hyper link such that it is not easily editable by user..Suppose I have list of values that are shown in hyper link.
<?=$row['p_name'] ?>
Now I want to navigate to view.php where I want to get back value of $row['p_id'] from the title. Is their any way to do So? What are other functions that encrypt on manage.php and decrypt again view.php page?
You appear to be confusing encryption and integrity assessment.
Integrity assessment:
If your purpose is detect when the user modified the values passed on the URL, a hash code (sometimes known as a Message Digest or a Checksum), such as one produce with SHA256 can suffice.
Simply add the URL an extra parameter value with a hash code. This hash code value can be produced by feeding the hash algorithm with the values which integrity you wish to assert, maybe along an extra secret "key" value (aka "salt"). Upon receiving a request, first verify that the hash produced by the values on the URL matches the hash of the URL; if it doesn't at least one value on the URL was altered.
Encryption:
If your purpose is to hide from the user and others what kind of data/values are passed on the URL, encryption is necessary. Unlike a hash, Encryption algorithms can be reversed and produce back the original input from the encrypted text.
In most cases, encryption can also provide data integrity validation, because it is difficult for someone to alter the encrypted text in a way that it can be decrypted to a structurally valid text. Many encryption algorithms are such that altering even just one or two bytes in the encrypted text, results in producing "gibberish" at decryption time.
Practical suggestions with PHP:
for hashing, use one of: crc32(), md5() and the like. (or also hash() as shown in the question's code snippet).
for encryption, use mcrypt_encrypt() / mcrypt_decrypt() from the MCrypt module
depending on the algorithms used, remember to convert the encrypted output base64 or other format so that it can be part of a URL (many hashing and encryption methods produce binary data that include many characters susceptible of "breaking" urls)
if you don't need more secret encrypt ,try using base64_encode/base64_decode
If you only need the data to be tamper proof you could use hash_hmac

Categories