PHP code:
$key = "12345678abcdefgh12345678abcdefgh";
$iv = "12345678abcdefgh";
$plaindata = "This is a test string.";
$enc = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaindata, MCRYPT_MODE_CBC, $iv));
echo($enc);
Result:
QBN0Yue3D9hBrBuD01n5KWG+lv2doMf97cKm/AeusAI=
How can this be decrypted in Python?
Try something like this (altho i do have PyCrypto installed)
from Crypto.Cipher import AES
import base64
AES.key_size=128
iv="your iv"
key="your key"
crypt_object=AES.new(key=key,mode=AES.MODE_CBC,IV=iv)
decoded=base64.b64decode(plain) # your ecrypted and encoded text goes here
decrypted=crypt_object.decrypt(decoded)
This will bring the decoded text but it will be padded with bytes for it to be a size multiple of 16.
You should probably decide on a proper padding scheme and remove it afterwards accordingly
Read the manual, its pretty well documented.
data = base64.b64decode('QBN0Yue3D9hBrBuD01n5KWG+lv2doMf97cKm/AeusAI=')
Related
Hello everyone i was trying to decrypt some encrypted strings i encrypted with python .
the problem is that sometimes it decrypts correctly and sometimes it gives empty output for no obvious reason and i couldn't find any solution for it.
here's the code i'm using to decrypt on PHP .
knowing that online AES decryption tools decrypts it correctly.
$rtk=base64_decode('zgdHfETipvp1E5m3ix5NFOLuX8N0+zAIBzg+GOq0cTQ=');
$method = "aes-128-ecb";
$key = 'aaaaaaaaaaaaaaaa';
$email=openssl_decrypt($rtk, $method, $key,OPENSSL_RAW_DATA);
i would apreciate your help !
EDIT :
The python code i used to encript the string :
import pandas as pd
from Crypto.Cipher import AES
import names
import urllib.parse
import base64
from Crypto.Util.Padding import pad
from Crypto.Util.Padding import unpad
email="zqeafzeqaf23#example1.com"
key = b'aaaaaaaaaaaaaaaa'
data = email.encode('ascii', 'ignore')
cipher = AES.new(key, AES.MODE_ECB)
b64string = base64.urlsafe_b64encode(cipher.encrypt(pad(data,16)))
print(b64string)
Your Python code uses urlsafe_b64encode, but your PHP code uses the normal base64 variant (in fact your example data in the PHP code contains a + character so couldn’t have been produced by that Python code).
This could explain why the decryption is failing. If the url safe base 64 output from Python contains a - or _ character, PHP will simply strip that character from the string before decoding the rest of it. This will leave a string that is not a multiple of the AES block length and the decryption will fail.
You should ensure you are using the same base 64 variant to encode and decode. It doesn’t look like PHP provides a URL safe variant, you might need to use something like strtr before decoding to convert the base 64 into a normal variant:
$data = strtr($data, '-_', '+/');
$decoded = base64_decode($data);
I am working on decrypting some content coming from an API. They have provided a command as well. So with some mofication below is the command, which works perfectly fine:
openssl enc -d -aes-128-cbc -K 422943374a3568755d7c527f6e472132 -iv 00000000000000000000000000000000 -nopad -in <(echo 'D5fiXKI4ie4c69gcCwM4/p414yrYtH9np+piNoqZASbkUnHAvbB4norHz6d6uzJmIg1sULhHFmfQTkvpw0tIEVmNcjyP6j2LK8zXYzohtNlsqBHx5v4xHEIyCcvfbMJddd5hs97jqkUtHuQyer2GdfDKZseaGgpXJ75GK7uKFPkbJ3wgQ6A0Q7q2tbBYeXEDmRMO6OhWeHgrezQOcyjcdOQk50SjMuaSb9IRimwagXamiXRg0LyTzA18a0SuqtbKCNgXnmhf39YxJUudkRmcMQ==' | base64 --decode)
I need to code in PHP, so I need to translate same thing in PHP, and here is what I have written in PHP:
$encodedStr = "PYroeIibeYwy/waD3opLw6yWT6Wfv3AhBKhQpoR+6qT9gx/bTDdR9QIfXcVURoQ2QlTl8L+JZX4Ije8M+FAQOxVmEXAmyUpzLgeg7aRCA6iiJbav/W3xW0BWb3D3QELjKTN4KRB2FdM7G5eIIfvjpeySLxQ3h7eL16nQf+1rms4VoVsBaeO8aU+Zy9saKZR4oL+k40m6tjtvtXryg7sWcmUgdonP/Jg4osESrY3MmGl7qXSpJC+v4g3iOY7s8NwywSN9q2Id7P0IaVtb5AFOEQ==";
$secretHash = ",MF-,2Y*s8DoYCFI";
$encryptionMethod = "AES-128-CBC";
$iv = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
$encrypted = base64_decode($encodedStr);
$hexKey = strToHex($secretHash);
$response = openssl_decrypt($encodedStr, $encryptionMethod, $hexKey, OPENSSL_ZERO_PADDING, $iv);
And in response, I am getting a string of odd characters instead of actual string which I can get from openssl command in command line.
As per openssl_decrypt documentation:
Takes a raw or base64 encoded string and decrypts it using a given method and key.
I have also tried giving base64 decoded value as well in first argument of this function. Encryption method also seems fine. And Zero padding as told in API document. Only thing which I think can be doubtful is zero iv. Let me know if I am making zero iv in wrong way. I have tried not using iv as well but not useful. Or also let me know if I am doing wrong in something else.
openssl_decrypt expects key to be binary not hex. You don't need to convert $secretHash to hex and just pass it as is.
$response = openssl_decrypt($encodedStr, $encryptionMethod, $secretHash, OPENSSL_ZERO_PADDING, $iv);
I have this issue where something is encrypted in python using aes 256 cbc encryption as shown in the python codes encrypt method .
I am trying to create a Decrypt method in php to actually decrypt whats encrypted using the python class .
Here is my attempt to convert the python decryption method to php does it look right or am I missing something in my conversion as every time i use the php version to decrypt it says hmac failed ?
anyhelp in converting the python class to php i will appreciate.
public function decrypt(){
$encrypt_method ="AES-256-CBC";
$secret_key =base64_decode('samekeyusedintheencryption');
$encrypted=(string)'some encrypted text to be decrypted';
$data=json_decode(base64_decode($encrypted),true);
$secret_iv =base64_decode($data['iv']);
$output = \openssl_decrypt($data['value'],
$encrypt_method,$secret_key,0,$secret_iv);
return json_encode($output);
}
def decrypt(self, payload):
data = json_c.decode(base64.b64decode(payload))
value = base64.b64decode(data['value'])
iv = base64.b64decode(data['iv'])
crypt_object=AES.new(self.key,AES.MODE_CBC,iv)
plaintext = crypt_object.decrypt(value)
return loads(plaintext)
OK, I got it to work!
function decrypt($encryptedText, $secret_key){
$secret_key = base64_decode($secret_key);
$encrypt_method ="AES-256-CBC";
$data = json_decode(base64_decode($encryptedText),true);
$data['iv'] = base64_decode($data['iv']);
$data['value'] = base64_decode($data['value']);
return openssl_decrypt($data['value'], $encrypt_method, $secret_key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $data['iv']);
}
Some things I learned:
If the options in the openssl function are set to '0' it expects a base64_encoded input for the cipher text. Also, if the default options is set to '0' the padding default is set to PKCS#7. This, I think, is why we were getting the bad block size error.
So, the cipher text needs to be base64_decoded and we need to set both options for the padding.
I was able to decrypt your provided cipher text and see the email addresses.
You are provided the MAC in the Data array so this would allow you to check the MAC in the PHP script. This allows you to make sure the data has not been tampered with.
I recently did an encryption project and started with the open ssl, but ended up changing to the libSodium library. I highly recommend you check it out for any further projects.
Cheers!
I'm a noob developer and I'm trying to decrypt some data but when I use OpenSSL in PHP I received no response. Also, when trying to encrypt data OpenSSL add a block of characters.
This is the code:
<?php
$dataToDecrypt = hex2bin("C2E5CDFE8BBFBC7350D40538434824DD3E11520B89A5BFDE24FA064DB2EED6EA");
$aesKey = hex2bin("E3FB8EA130722FA99266B96B77C2735C39393939393939393920202020202020");
$iv = hex2bin("00000000000000000000000000000000");
$result = openssl_decrypt($dataToDecrypt, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);
echo bin2hex($result);
?>
The $result is supposed to be:
C3A6149C73FFBE4EAD36DC62FE40877D17CD690F37B06058CA3D65A345CC8212
I've tried this on VB and even in a AES encription web page (http://aes.online-domain-tools.com/) and the result is correct. But when trying with PHP I've got no answer.
I noticed when encrypting with the same information, the encrypted data is different. This is the code:
<?php
$dataToEncrypt = hex2bin("C3A6149C73FFBE4EAD36DC62FE40877D17CD690F37B06058CA3D65A345CC8212");
$aesKey = hex2bin("E3FB8EA130722FA99266B96B77C2735C39393939393939393920202020202020");
$iv = hex2bin("00000000000000000000000000000000");
$result = openssl_encrypt($dataToEncrypt, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);
echo bin2hex($result);
?>
When I encrypt the result is:
C2E5CDFE8BBFBC7350D40538434824DD3E11520B89A5BFDE24FA064DB2EED6EA3A3ED407DC78D6AF9030BAB90CB40EAD
I get 32 characters more than expected (3A3ED407DC78D6AF9030BAB90CB40EAD). When I encrypt in VB or using the web page mentioned before I don't get these 32 extra characters.
Why is this happening? Am I missing something? I've been searching for an answer for several days. Any help is appreciated.
To see something during PHP decrypt you need to turn on warning messages.
Essentially the openssl_decrypt call will first decrypt your ciphertext. As long as your ciphertext is a multiple of 16 bytes (the block size of AES) this will always succeed. After that it will try and perform PKCS#7 compatible unpadding, which will fail (with high probability). To make it not unpad, use the OPENSSL_ZERO_PADDING in addition to OPENSSL_RAW_DATA.
The same goes for your encryption function of course. Currently you receive the ciphertext of the padded plaintext. This will add exactly one block of padding if the input plaintext is a multiple of the block size (and it is in your sample code). So you need OPENSSL_ZERO_PADDING there as well.
I'm using NSData+AESCrypt category by Jim Dovey and NSString+AESCrypt by Michael Sedlaczek (2011-02-22).
And on PHP I have a simple script:
<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = '01234567890123456789012345678901';
$plaintext = "myworda";
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_ECB);
$base64encoded_ciphertext = base64_encode($ciphertext);
echo "ciphertext: ".$base64encoded_ciphertext."<br/>";
?>
In ObjC:
NSString *key = #"01234567890123456789012345678901";
NSString *plaintext = [#"+l56Ia4yyK19D2x2+oCXuw==" AES256DecryptWithKey: key];
NSLog(#"plaintext: %#", plaintext);
I change the variable $plaintext in PHP, run script and copy and paste the output-cipher to the Objective-c to decrypt it.
And:
"myword" gives me "+l56Ia4yyK19D2x2+oCXuw==" and I decrypt in and get "myword" on iOS [OK]
"good morning" gives me "5UdImsV1pQs60ovXmH74HQ==" and I decrypt in and get "good morning" on iOS [OK]
"Schröder" gives me "KqNSCE8nGsYUYVdGZ2tnMw==" and I decrypt in and get "Schröder" on iOS [OK]
"Schröder" gives me "KqNSCE8nGsYUYVdGZ2tnMw==" and I decrypt in and get "Schröder" on iOS [OK]
"very long text" gives me "lsa+QF3IHQnAFiOjl2Heyg==" and I decrypt in and get "very long text" on iOS [OK]
"very very very very long text" gives me "kl/ThEyuyUMmKSqU4/fJSzzJOyvsXrGRt5/zsnqjQww=" and I cannot decrypt it on iOS [FAIL]
Why #5 fails? If I try to encrypt "very very very very long text" using Xcode, I get "kl/ThEyuyUMmKSqU4/fJS90UZoJ73S4gox2uCoWoIL8=" notice that:
kl/ThEyuyUMmKSqU4/fJS == kl/ThEyuyUMmKSqU4/fJS
zzJOyvsXrGRt5/zsnqjQww != 90UZoJ73S4gox2uCoWoIL8=
But going further, encrypting "good morning" on Xcode gives me "hVq1AuR8PAXSOztK26pmMw==", while PHP gave "5UdImsV1pQs60ovXmH74HQ==", but Xcode decrypts both to "good morning" using the same key.
Please help.
Your PHP code is using ECB mode. I cannot see where you are setting the mode in ObjC. Presumably you are using its default mode. It is possible that the ObjC default mode is not ECB, more likely CBC. Also notice that whenever your plaintext is 16 bytes or less (that is one block or less) the decryption works. When it is greater than 16 bytes (that is it extends into a second block) it fails.
I suspect that the ObjC default is CBC mode with a zero IV. That will act as if it is ECB for the first block only, and differ for the second and subsequent blocks.
ECB mode is unsafe and leaks information. Use CBC mode with a specified IV instead. At the very least change your PHP code to use CBC mode instead of ECB mode.
You encrypt the message using MCRYPT_RIJNDAEL_128 which gives you a block size of 128 bits, or 16 bytes.
You'll notice that very very very very long text is larger than 16 bytes.
So I'm guessing you're decryption on ios uses a different block size. I'm not familiar with ios, but AES256DecryptWithKey seems to indicate it uses a block size of 256 bits.
Try using MCRYPT_RIJNDAEL_256 in your PHP code, or change the ios code to use AES128DecryptWithKey (I don't know if that exist, again, I don't know ios)