Need to know if I can step through PHP code to understand what the code is doing.

I have some PHP code from a Word Press plugin that I am trying to understand.

The situation is that we are using this plug-in to encrypt data on a web site, which uses the OpenSSL lib and AES-CBC encryption.   I need to decrypt the data in a outside system.   I have VBA code to decrypt AES, but I can't get it to work.

The plug-in has a test and verification tool where you can type a string, it encrypts it, shows the encrypted text, and then the decrypted text as a check to verify that everything is working correctly.   What I am doing  is copying the encrypted text and then trying to decrypt with VBA as a test.

I have looked through the plug-in code and found the procedures they are using as part of their verification tool, but I don't fully understand PHP code.

Is there any way on a Word Press site using PHP code that I can step through the code as it executes and inspect variables?  That would be very helpful in figuring this out.

If not, I will post the code in another question for help in figuring out the steps that are being used.

LVL 59
Jim Dettman (Microsoft MVP/ EE MVE)President / OwnerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Hi Jim,

Just update this question with your PHP and VBA code.

To step through PHP code, you have to jump through a variety of hoops that are often ridiculous in comparison to what you actually get. Remember, your standard debugging tools let you step through code because that code is sitting on your own computer and is executing from there, so the debugger has full control of the situation. With PHP, the code is executing on the server, so in order to do debugging, you often have to have a special debugging extension installed on the server, and then a client to communicate with that extension in order to send back and forth messages like "Stop", "Continue", etc...

Plus, in this case, most of the guts are going to be hidden behind the compiled OpenSSL extension, so all you're going to be able to see in a debugger anyway are the parameters, which might not necessarily help you (and you could just write those parameters to a file anyway if you wanted to capture them, instead of trying to use a full-fledged debugger).

You mentioned you're copying and pasting the encrypted text - I'm assuming that means that you're letting the encryption also finish with an implicit base64 encoding (so the result is all printable ASCII characters that you can safely copy and paste), so if that's the case, then make sure your VBA code is decoding Base64 first before you decrypt.
Jim Dettman (Microsoft MVP/ EE MVE)President / OwnerAuthor Commented:
which might not necessarily help you (and you could just write those parameters to a file anyway if you wanted to capture them, instead of trying to use a full-fledged debugger).

 I may need to do that in order to see what's going on.   We're trying to get support on the plug-in from the author (this is Gravity Forms Encryption), but from past comments, it seems like they will not answer these types of questions and not knowing PHP, I'm stuck.

Just update this question with your PHP and VBA code.

 Below is the PHP code.   I'm using the OpenSSL encryption and where I'm getting hung-up is what their doing with the $key in various places.  For example, what they are doing on lines 45-47 (gfef_get_key()).

 For their test utility, I tried using:

tester 12345678

 and got this as an encrypted string:

GFEncrypt: d88990c33652062f989dfc279ac1dlaTJQSlpaNlp2NFIzKytRcUYxUT09

 I know the basics of encryption, what MD5, and SHA256 is, etc, but haven't worked with them a ton, and I can reference all the standard PHP calls, but things like concatenation is what I'm getting lost with.    For example, I can't figure out if 'GFEncrypt:' is being passed in as part of the encrypted text of if that is being stripped of (I believe it is - line #58).    Also what is being done with $iv.

 I'll stop here and let you review.


// Decrypt
function gfef_decrypt($text, $key = null) {
                $use_mcrypt                                     = apply_filters('gform_use_mcrypt', function_exists( 'mcrypt_decrypt'));
                $use_openssl                                    = function_exists('openssl_encrypt') && extension_loaded('openssl');
                $gfe_type                                           = get_option('gfe_encryption_method');
                $gfe_key                                             = false;
                if (get_option('gfe_encryption_key')) {
                                $gfe_key                             = md5(esc_html__(get_option('gfe_encryption_key')));
                $secure_key                                      = substr($text, 0, 11);
                $key                                                      = gfef_get_key($gfe_key, 'decrypt');
                if ($secure_key === 'GFEncrypt: ') {
                                $secure_key = 'locked';
                } else {
                                $secure_key = 'unlocked';
                if ($gfe_type == 2 && $use_mcrypt && $gfe_key && $secure_key === 'locked') {
                                $mcrypt_cipher_name = MCRYPT_RIJNDAEL_128;
                                $iv_size                                = mcrypt_get_iv_size($mcrypt_cipher_name, MCRYPT_MODE_CBC);
                                $text_decode                   = substr($text, 11);
                                $iv                                          = substr($text_decode, 0, $iv_size);
                                $text_decode                   = base64_decode(substr($text_decode, $iv_size + 10));
                                $decrypted_value           = trim(mcrypt_decrypt($mcrypt_cipher_name, $key, $text_decode, MCRYPT_MODE_CBC, $iv));
                } else if ($gfe_type == 1 && $gfe_key && $use_openssl && $secure_key === 'locked') {
                                $decrypted_value           = gfef_ssl_decrypt($text, $key);
                } else {
                                $decrypted_value           = $text;
                return $decrypted_value;

function gfef_get_key($gfe_key, $operation) {
                $gfe_key_override                         = esc_html__(get_option('gfe_encryption_key_override'));
                if ($operation) {
                                if ($operation === 'decrypt') {
                                                if ($gfe_key_override) {
                                                                $gfe_key = md5($gfe_key_override);
                $password                                                          = "!c64l?" . trim($gfe_key) . "h4s?09aq-p3x";
                $salt                                                                       = gfef_get_salt() === false ? gfef_create_salt(false) : gfef_get_salt();
                $key                                                                      = md5(hash('SHA256', $salt . $password, true));
                return $key;

// OPEN SSL Decrypt
function gfef_ssl_decrypt($text, $key) {
    $ssl_cipher_name = "AES-256-CBC";
    $key                                   = hash('sha256', $key);
   $iv_size                             = openssl_cipher_iv_length($ssl_cipher_name);  // iv for AES-256-CBC = 16 bytes
   $text_decode                = substr($text, 11);
    $iv                                       = substr($text_decode, 0, $iv_size);
    $text_decode                = substr($text_decode, $iv_size + 10);
    $text                                 = trim(openssl_decrypt(base64_decode($text_decode), $ssl_cipher_name, $key, 0, $iv));

    return $text;

Open in new window

So that's your decrypt code, and it might help to understand that there are 2 extensions for doing crypto work in PHP - there's "mcrypt" which is old and deprecated and then there's "openssl". It would be important to know which one is being used, since it seems there are plugin settings that might impact the flow here.

So just a quick primer - AES and Rijndael can be considered the same thing for the current intents and purposes (their differences shouldn't matter within this code). In AES, you're using 128-bit blocks (16-bytes), and the difference between ciphers like AES-128 and AES-256 are the key lengths (16-byte key for AES-128, 32-byte key for AES-256, etc).

The initialization vector is typically stored as the beginning block of code, so this code basically looks like it sets up encrypted text so that it follows the convention of "GFEncrypt: <IV><Base64-encoded encrypted data>".

So the decryption routine should:
1. Trim off the "GFEncrypt: " at the beginning (the first 11 characters when you include the trailing space)
2. Take the first 16 bytes as the IV.
3. Base64-decode the remaining bytes AFTER the IV (byte 17 and on) to get the REAL encrypted data

Now, as far as the key goes, it seems like the OpenSSL code flow goes one way while the Mcrypt code flow goes another way. If you're on PHP 7 or later, you're almost certainly using OpenSSL, so I'd suggest just dumping the key to a file right before you run the decrypt:

$text_decode                = substr($text_decode, $iv_size + 10);
file_put_contents("decryption.key", $key); // <-- Add this line
$text                                 = trim(openssl_decrypt(base64_decode($text_decode), $ssl_cipher_name, $key, 0, $iv));

...then run your decryption routine in PHP and look for that "decryption.key" file. Then you should be able to edit the file with a text editor and take that key as its contents and ensure your VBA code is using that as the correct key.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Jim Dettman (Microsoft MVP/ EE MVE)President / OwnerAuthor Commented:
so I'd suggest just dumping the key to a file right before you run the decrypt:

Excellent....that should get me going.   In the plug-in settings, there is a "web site key" and a "password key", but no where could I find what was being used and how.   Writing the key like that will help a lot (which is why I asked about stepping through the code at first).

So the decryption routine should:

I'll try that and let you know.

and it is using OpenSSL BTW

Jim Dettman (Microsoft MVP/ EE MVE)President / OwnerAuthor Commented:
Doesn't look like I'm going to get this resolved for a few days yet.   I need to dig up (or write) some VBA code to do the SHA256 hash.

 So I'm going to go ahead and close this out.  Will ask another question if I get stuck again.

Jim Dettman (Microsoft MVP/ EE MVE)President / OwnerAuthor Commented:
Understood the question, got right to the point, and gave me exactly what I needed!

Jim Dettman (Microsoft MVP/ EE MVE)President / OwnerAuthor Commented:
This new closing process...yuck.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.