About RC4 Decryption PHP (mcrypt) - php

I'm looking for anything about RC4 Decryption with decode the input using: Hexa
Lucky for me, I found
PHP's mcrypt_encrypt.
I want to decrypt many cipher files with the same key.
But, I had a problem with:
$iv_size = mcrypt_get_iv_size(MCRYPT_ARCFOUR, MCRYPT_MODE_STREAM);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
print (mcrypt_decrypt(MCRYPT_ARCFOUR, $key, $text, MCRYPT_MODE_STREAM, $iv));
(And UTF-8 Vietnamese)
The result of echo $iv_size is 0.
Please help me, I don't know how I can fix it?
Key : Lyr1cjust4nct (key file .txt)
Mode: STREAM
Decode the input using: Hexa
Ciphertext: cipher.txt (Hexa)
http://pastebin.com/bmYcmU0J

RC4 doesn't support IVs. You instead need to use a unique key for each message.
RC4 has two big weaknesses that apply to your situation:
Using related keys is not secure. So you can't just concatenate a fixed key with a variable/unique IV. You'd need to use some kind of hashing scheme.
The beginning of the output is very biased, which leaks information about the ciphertext. So you need to throw away the beginning of the key-stream. I think throwing away 1024 bytes should take care of the biggest biases.
RC4 doesn't include any integrity protection (MAC). So if an attacker manipulates the ciphertext, you'll run into problems.
=> Don't use RC4. Use AES in an authenticated mode such as GCM or by combining AES with a MAC using the encrypt-then-MAC principle.
I strongly recommend using a high level library written by experts, since people get encryption wrong very often, even when using standard primitives like AES.

Related

How to encrypt plaintext with AES-256 CBC in PHP using OpenSSL?

I am trying to encrypt sensitive user data like personal messages in my php powered website before entering into the database. I have researched a bit on the internet and I have found the few important things to remember:
Never use mcrypt, it's abandonware.
AES is based on the Rijndael algorithm and has been unbroken till now.
AES has also been recommended by NSA and used in US Government data encryption, but since the NSA is recommending it, there's a chance they might sneak upon my user data easily.
Blowfish has been unbroken as well, but slow and less popular.
So, I decided I will give it a try first with AES-256 cbc. But I am still not sure if I should not consider Blowfish a better option. So any recommendations are welcome.
And my primary concern is, how to encrypt the data in php? I don't find a good manual about this in the php documentation. What is the correct way to implement it?
Any help is heavily appreciated.
AES-256 (OpenSSL Implementation)
You're in Luck.
The openssl extension has some pretty easy to use methods for AES-256. The steps you need to take are basically...
Generate a 256-bit encryption key (This needs storing somewhere)
$encryption_key = openssl_random_pseudo_bytes(32);
Generate an "initialization vector" (This too needs storing for decryption but we can append it to the encrypted data)
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
encrypt data using openssl_encrypt()
openssl_encrypt($data, 'aes-256-cbc', $encryptionKey, $options, $initializationVector)
the $options can be set to 0 for default options or changed to OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
append the initialisation vector to the encrypted data
$encrypted = $encrypted . ':' . $iv;
retrieve the encrypted data and the initialization vector.
explode(':' , $encrypted);
decrypt data using openssl_decrypt()
openssl_decrypt($encryptedData, 'aes-256-cbc', $encryptionKey, $options, $initializationVector)
Enabling openssl
openssl_functions() won't be available by default, you can enable this extension in your php.ini file by uncommenting the line. ;extension=php_openssl.dll by removing the leading ;
PHP - Fiddle.
http://phpfiddle.org/lite/code/9epi-j5v2

Decrypting the .ASPXAUTH Cookie WITH protection=validation

For quite sometime I've been trying to decipher the ASP .ASPXAUTH cookie and decrypt it using PHP. My reasons are huge and I need to do this, there is no alternative. In PHP so far I have successfully managed to read the data from this cookie, but I cannot seem to do it while it is encrypted. Anyway, here it goes...
First you need to alter your servers Web.config file (protection needs to be set to Validation):
<authentication mode="None">
<forms name=".ASPXAUTH" protection="Validation" cookieless="UseCookies" timeout="10080" enableCrossAppRedirects="true"/>
</authentication>
Then in a PHP script on the same domain, you can do the following to read the data, this is a very basic example, but is proof:
$authCookie = $_COOKIE['_ASPXAUTH'];
echo 'ASPXAUTH: '.$authCookie.'<br />'."\n";//This outputs your plaintext hex cookie
$packed = pack("H*",$authCookie);
$packed_exp = explode("\0",$packed);//This will separate your data using NULL
$random_bytes = array_shift($packed_exp);//This will shift off the random bytes
echo print_r($packed_exp,TRUE); //This will return your cookies data without the random bytes
This breaks down the cookie, or at least the unencrypted data:
Now that I know I can get the data, I removed the 'protection="validation"' string from my Web.config and I tried to decrypt it using PHP mcrypt. I have tried countless methods, but here is a promising example (which fails)...
define('ASP_DECRYPT_KEY','0BC95D748C57F6162519C165E0C5DEB69EA1145676F453AB93DA9645B067DFB8');//This is a decryption key found in my Machine.config file (please note this is forged for example)
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, ASP_DECRYPT_KEY, $authCookie, MCRYPT_MODE_CBC, $iv);//$authCookie is the pack()'d cookie data
This however fails. I've tried variations of IV with all zeros # 16 bytes. I've tried different Rijndael sizes (128 vs 256). I've tried base64_decode()ing, nothing seems to work. I've found this stackoverflow post here and started using variations of the key/iv that are made using sha256, but that isn't really working either.
Anybody have a clue what I should do?
I don't know how encryption is made in .NET AuthCookies, but I can try to answer.
Assuming the encryption occurs in AES CBC-IV mode, with randomly generated IVs, you need to first find out where the IV is.
The code snippet you show cannot work, as you are generating a random IV (which will be incorrect). That being said, even if you get the IV wrong, in CBC mode you will only have the first 16 bytes of your decrypted ciphertext "garbled" and the rest will decrypt properly - you can use this as a test to know if you're doing the rest correctly. In practice when using random IVs, it's very likely that it's prepended to the ciphertext. To check if this correct, you can try to check if len(ciphertext) = len(plaintext) + 16. This would mean that most likely the first 16 bytes are your IV (and therefore it should be removed from the ciphertext before attempting to decrypt it).
Also on your code snippet, it seems you are using the key as an ascii-string, whereas it should be a byte array. Try:
define('ASP_DECRYPT_KEY',hex2bin('0BC95D748C57F6162519C165E0C5DEB69EA1145676F453AB93DA9645B067DFB8'));
Also, this seems to be a 32 byte key, so you need to use AES-256. I don't know how the authcookie looks like, but if it's base64 encoded, you also need to decode it first obviously.
Hope this helps!
Note: I don't recomment doing this for important production code, however - because there are many things that can go wrong if you try to implement even your own decryption routine as you are doing here. In particular, I would guess there should be a MAC tag somewhere that you have to check before attempting decryption, but there are many other things that can go wrong implementing your own crypto.
I understand this may not have been possible for the OP but for other people heading down this route here is a simple alternative.
Create a .net web service with a method like:
public FormsAuthenticationTicket DecryptFormsAuthCookie(string ticket)
{
return FormsAuthentication.Decrypt(ticket);
}
Pass cookie to web service from PHP:
$authCookie = $_COOKIE['.ASPXAUTH'];
$soapClient = new SoapClient("http://localhost/Service1.svc?wsdl");
$params= array(
"ticket" => $authCookie
);
$result = $soapClient->DecryptFormsAuthCookie($params);
I know what a pain is to decrypt in PHP something encrypted in .NET and vice versa.
I had to end up coding myself the Rijndael algorithm ( translated it from another language ).
Here is the link to the source code of the algorithm: http://pastebin.com/EnCJBLSY
At the end of the source code there is some usage example.
But on .NET, you should use zero padding when encrypting. Also test it with ECB mode, I'm not sure if CBC works.
Good luck and hope it helps
edit: the algorithm returns the hexadecimal string when encrypts, and also expects hexadecimal string when decrypting.

PHP (mcrypt_encrypt) Ruby (AES-256-CBC) Encryption Different Results

I have been trying to encrypt a string in PHP and Ruby using the same key and iv but I always got different results.
Below is the PHP Code
$data = "This string needs to be encrypted";
$key = "1234567887654321abcdefghabcdefgh";
$iv = "1234567887654321abcdefghabcdefgh";
echo $encrypted_data = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
Below is the Ruby Code
data = "This string needs to be encrypted"
key = "1234567887654321abcdefghabcdefgh"
iv = "1234567887654321abcdefghabcdefgh"
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
aes.encrypt
aes.key = key
aes.iv = iv
encrypted_data = aes.update(data) + aes.final
Could somebody please help me get the same encrypted data in PHP and Ruby? I encrypted some data in PHP and then decrypted in Ruby but didn't get the data back. So I think the issue is PHP and Ruby encryption and decryption mechanism work differently. Please correct me if I am wrong. Thanks
Don't hard code IV's , it is insecure. IVs must be random but can be public , so just use
mcrypt_create_iv and prepend it to the front of the ciphtertext and then extract it before
decrypting
You likely have three problems
MCRYPT_RIJNDAEL_256 is nott AES. AES is a specific version RIJNDAEL that was standardized with a 128 bit block size and either 128 or 256 bit keys. MCRYPT_RIJNDAEL_256 is RIJNDAEL with a 256 bit block size. You want to use MCRYPT_RIJNDAEL_128 which is actually AES. For php, key length is just determined by the length of the key. So just give it a 256 bit ( 32 character) key and you will be fine. Note block size does not effect security really, so don't worry about the deference and just use AES with a 256 bit key: its good enough for the NSA and top secret data.
Padding. AES only takes fixed 128 bit chunks, so you must pad out the text to be a multiple of that size. PHP doesn't really bad and i believe SSL uses pkcs7 padding. Note that even with different padding schemes, for most of them the start of the cipher text should the the same there just may be garbage at the end.
String encoding. AES is defined with bit inputs, in c typically this is a byte array. Ruby and PHP use strings. I'd be willing to bet your string encodings are different.

Encrypt / Decrypt with Private key

I would like to implement some security in some of the Flash/PHP applications that I have.
I have some Flash apps that communicate with PHP files, and the PHP is sending the data as get string ( e.g.: name=John&sname=Doe&age=24&balance=12.4 ). Instead of all these variables, I would like it to send a single variable ( e.g.: flashvar=jr9afgaw9-fg90agfawf7gw ) that would contain those values, so then Flash would decrypt the string and get the real and useful vars.
I want to encrypt this using a private key and use the same private key to decrypt this inside Flash. If someone would want to decode the message PHP sends, he would have to decompile the flash file and find the private key I'm using in Flash to decode the message and then decode it.
The reason I posted here is because I want to use an encryption algorithm that allows only the use of a private key for encryption/decryption.
I'm new in the cryptography field and I'd like some suggestions for this.
Thank you!
A "shared private key" is refered to as a symmetric key. The standard symmetric algorithm in use today is AES. I have no idea if php, or flash, have the capability of using AES (Google does), but if they do, you could hard code an AES key in your code and use it to encrypt and decrypt data. However, hard coding a key is very bad cryptography and is little more than obfuscation.
Another thing to keep in mind is the cipher mode you are using. Cipher Block Chaining (CBC) requires the use of an initialization vector (sort of like a salt for a hash), so two of the same values encrypted with the same key, but different IV, will result in differen cipher text. ECB does not need an initialization vector, but is less secure. For your needs I would go with ECB so you dont have to worry about an IV.
Google is a very good way of finding information, you should use it.
After a quick search, I saw that ActionScript 3 has support for encryption throught ASCrypt3 library. According to the website, AES Rijndael is supported.
Rijndael is also supported in PHP using the mcrypt extension. Here's a pretty good example taken from the manual:
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$text = "Meet me at 11 o'clock behind the monument.";
echo strlen($text) . "\n";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
If You want to encrypt data I would go with the ASCrypt3o library.
It works very well and supports multiple types of encryption.
You can see a demo of it here click on the secret key tab.

Can I replicate the exact behaviour of PHP's AES encryption in ruby?

I'm in the process of rebuilding a PHP web app in Ruby on Rails, and would dearly love to avoid forcing all existing users to reset their encrypted passwords. The PHP site uses mcrypt_encrypt with AES-256-ECB, and I can't for the life of me get the same cipher text using ruby's OpenSSL. I can't decrypt them either (which is good in principle) since what's actually stored in the user DB is an MD5 hash of the AES cipher text.
I've read these previous, closely related questions and the very helpful answers:
How to make Ruby AES-256-CBC and PHP MCRYPT_RIJNDAEL_128 play well together
Part II: How to make Ruby AES-256-CBC and PHP MCRYPT_RIJNDAEL_128 play well together
including the pages referenced there, and if I understand correctly, the PHP and ruby implementations use different padding methods. Since I have to live with how things work on the PHP side, is there any way to force the same padding method on ruby/OpenSSL somehow? I'm using ruby 1.9.2-p180.
Here's the sample code in PHP:
$salt = "12345678901234567890123456789012";
$plain = "password";
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $plain, MCRYPT_MODE_ECB, $iv);
echo md5($cipher);
Output: 6337137fd88148250fd135a43dbeb84a
and in ruby:
require 'openssl'
salt = "12345678901234567890123456789012"
plain = "password";
c = OpenSSL::Cipher.new("AES-256-ECB")
c.encrypt
c.key = salt
cipher = c.update(plain)
cipher << c.final
puts Digest::MD5.hexdigest(cipher)
Output: 18dee36145c07ab83452aefe2590c391
Actually not in general an openssl solution but maybe it is ok for you to have a working example.
require 'mcrypt'
require 'openssl'
plaintext = 'password'
puts plaintext
key = '12345678901234567890123456789012'
enc = Mcrypt.new(:rijndael_256, :ecb, key, nil, :zeros)
encrypted = enc.encrypt(plaintext)
puts Digest::MD5.hexdigest(encrypted)
I used an additional gem(ruby-mcrypt). Seems to be an issue with openssl. Actually the issue seems to be that Openssl does not support zero padding and uses either no-padding or default-openssl-padding. Due to the fact that you use zero padding in php you must use zero padding also in ruby.
Output on my machine for the php script:
[~/test] ➔ php5 t.php
6337137fd88148250fd135a43dbeb84a
and for the ruby script:
[~/test] ➔ ruby t2.rb
password
6337137fd88148250fd135a43dbeb84a
and my ruby version:
[~/test] ➔ ruby -version
ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
Hope this helps.
if key size is not standard on php side, you need to fill the key with zeros to next valid key size, in order to make ruby side works like this:
php_encrypted = string_encoded_with_php_mcrypt
key = "longerthan16butnot24".to_a.pack('a24')
enc = Mcrypt.new(:rijndael_256, :ecb, key, nil, :zeros)
enc.decrypt(php_encrypted)
In this case next valid key length is 24.
For :rijndael_256 valid key lengths are: 16, 24, 32
You can get more info on algorithms:
Mcrypt.algorithm_info(:rijndael_256
if you can use other encrypt methods, you can try TEA Block Encryption. I have adopted the method across Ruby, JS, ActionScript. It should work with PHP as well. github repo is here

Categories