繁体   English   中英

如何解密用Openssl在bash脚本中加密的PHP文件

[英]How to decrypt a file in PHP that was encrypted in bash script with Openssl

我必须使用PHP的openssl_decrypt解密我的Laravel后端中的文件。 该文件在Laravel以外的BASH脚本和openssl 1.1中加密。

我看了一些可以帮助我但却没有发现任何有用的解释。 对于PHP和服务器,我的openssl版本都是相同的(1.1)。 我尝试了很多选项组合,但没有任何效果。

这是我的BASH加密脚本:

APP_KEY='**************'
FILES_PATH='****/app/files/'
# We're looking for ".decrypted" files, which gonna be encrypted next
FILES_LIST=$(find $FILES_PATH -type f -name '*.decrypted' )
# We base64-decode the key then display it as Hex. string
KEY=$(echo $APP_KEY | base64 -d -i | xxd -p -c 64)

# For each file to encrypt :
while read -r file; do
  # If there is actually a file :
  if [ ! -z "$file" ]; then
    output=${file%.decrypted}
    chunkspath="${output}.chunk."
    chunksname="${chunkspath##*/}*"
    # We have to split the files into 32M. chunks because our server can't decrypt big files without memory leaks in php.
    split -b 32M -d $file -a 3 $chunkspath
    chunkslist=$(find $FILES_PATH -type f -name $chunksname)
    touch $output
    # For each chunk :
    while read -r chunk; do
      # Generate a random IV of 16 bytes (output is 32 characters in Hex.)
      iv=$(openssl rand -hex 16)
      temp="${chunk}.enc"
      openssl AES-256-CBC -K $KEY -iv $iv -in $chunk -out $temp
      # We prefix each chunk with his IV to let the server retrieve it when decrypting. See the PHP code bellow.
      echo -n $iv >> $output
      # Then we append each IV+Chunk in the final output file.
      cat $temp >> $output
      rm $temp $chunk
    done < <(echo "${chunkslist}")
    # I commented the next line to let me run some tests but the original file will have to be removed eventually.
    # rm $file
  fi
done < <(echo "${FILES_LIST}")

echo 'Done'

这是我用于解密文件的PHP脚本:

// This function is inside a Laravel's stream download response 
    function () use ($file, $log) { // $file is the Laravel model representation of a stored file.
        $cipher = 'AES-256-CBC';
        $key = base64_decode(substr(config('app.key'), 7));
        $ivLen = 32; // Actually 16 bytes but 32 characters in hex format
        $chunckLen = 32 * 1024 * 1024; // Chunks are 32Mo long or less for the last one
        $fpIn = fopen(Storage::disk('files')->path($file->path), 'rb');
        while (!feof($fpIn)) {
            // IV and Key must be in binary format
            $iv = hex2bin(fread($fpIn, $ivLen));
            // We read the file chunks by chunks, decrypt it and print it.
            $encrypted = fread($fpIn, $chunckLen);
            $decrypted = openssl_decrypt($encrypted, $cipher, $key, OPENSSL_RAW_DATA, $iv);
            while ($msg = openssl_error_string()) {
                print $msg . "\n";
            }
            print($decrypted);
        }
    }

我希望解密的文件是可读的。 使用上面的代码,输出文件包含以下行: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt我尝试使用openssl_decrypt()方法中的OPENSSL_ZERO_PADDING选项。 然后输出文件包含二进制数据,但文件不可读(我猜这个ecryption没有按预期工作)。 我还尝试在bash脚本中设置-nopad选项,但随后抛出此错误: 4960:error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length:../openssl-1.1.1c/crypto/evp/evp_enc.c:425: . 有人知道错误是什么意思吗? 我做错了什么 ? 我几乎可以肯定我错过了一些东西(我在加密世界中有点新意......)

谢谢!

实际上我刚刚意识到脚本中使用的密钥和Laravel中使用的密钥不一样......愚蠢的我。 因此上面的代码是正确的,并解决了我的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM