Home > other >  Piping output of one command to the input of another in php
Piping output of one command to the input of another in php

Time:01-07

I'm attempting to run a bash command in a php script. Unfortunately, because the command contains a pipe to another command, it doesn't seem to work as simple as writing the actual bash command into proc_open, popen, or shell_exec. I'm trying to use openssl to decrypt an encrypted password. I have the encrypted password in a database and after I retrieve it I need to echo the encrypted pw and pipe it to openssl. This is the exact command I need to run in its basic bash format:

echo $encryptedPassword | openssl enc -base64 -d -aes-256-cbc -salt -pass pass: password -pbkdf2

Where password is the password I have chosen to use as a salt to encrypt it in the beginning which I'm obviously not going to put in the forum. I've tried to use proc_open, popen, and shell_exec and none of the info I've found online seems to work. There's very little information online for chaining commands within php which leads me to believe this may not be possible and I may have to take another approach. It seems there is a php openssl plugin, however my company is trying to keep things as basic as possible without installing additional components. I also feel like this would be good information to know for other command chaining as there won't always be a plugin to use.

Any help would be greatly appreciated.

CodePudding user response:

With the following command:
note: please notice the use of printf %s instead of echo (which adds a newline at the end).

printf %s 'stringPassword' |
openssl enc -base64 -aes-256-cbc -salt -pass pass:'password' -pbkdf2

You get:

U2FsdGVkX1/PdBwO5rCJrbn5dZ5cHb9w1lH2E1LECBw=

For deciphering it you have to:

  1. base64-decode the output of openssl.

  2. Get the salt, which is bytes 9-16 of the base64-decoded string.

  3. Derive a 48 bytes key using PBKDF2 with the given password, the salt and 10000 iterations of sha256 hashing (default of openssl -pbkdf2).

  4. Get the encryption key (which is bytes 1-32) and the iv (which is bytes 33-48) from the derived key.

  5. Get the ciphered text, which is bytes 17 through the end of the base64-decoded string.

  6. Decrypt the ciphered text using aes-256-cbc, the encryption key and the iv.


Now, let's try to decipher it with php:

function decrypt($data, $passphrase) {
    $d = unpack(
        'x8/a8salt/a*data',
        base64_decode( $data, true )
    );
    $k = unpack(
        'a32key/a16iv',
        openssl_pbkdf2( $passphrase, $d['salt'], 48, 10000, 'sha256' )
    );
    return openssl_decrypt(
        $d['data'],
        'aes-256-cbc',
        $k['key'],
        OPENSSL_RAW_DATA,
        $k['iv']
    );
}

var_dump( decrypt('U2FsdGVkX1/PdBwO5rCJrbn5dZ5cHb9w1lH2E1LECBw=', 'password') );
string(14) "stringPassword"

ASIDE: answering OP's initial question.

For calling the openssl command in a pipe inside php you can use shell_exec, but you SHALL prevent any potential code injection:

$cyphered = 'U2FsdGVkX1/PdBwO5rCJrbn5dZ5cHb9w1lH2E1LECBw=';
$password = 'password';

$text = shell_exec(
    'echo ' . escapeshellarg($cyphered) . ' | ' .
    'openssl enc -d -base64 -aes-256-cbc -salt -pbkdf2 -pass pass:' . escapeshellarg($password)
);

################

var_dump($text);
string(14) "stringPassword"

CodePudding user response:

It turns out the digest algorithm for openssl changed between versions. 1.0.2 and older used md5 as the digest. Anything newer than that uses sha256. Since I was encrypting with newer openssl but decrypting with an older openssl, on the decryption side with openssl I had to specify to use sha256 with the option -md sha256. Otherwise it would try to use the older md5 digest. A very helpful link that led me to this conclusion: https://bbs.archlinux.org/viewtopic.php?id=225863

  • Related