<?php
	/*  PHP7 Decrypt Test 1.1.1 */
	//
	//
	// 2020-0609 for Troi Encryptor Plug-in 6.0 for FileMaker Pro 19
	// by Troi Automatisering  https://www.troi.com
	//
	// This example assumes it is run on macOS (on Windows it needs to be modified).
	// You also need to export the data from FileMaker with the OpenSSL.fmp12 example (the export to desktop button)
	//
	// INSTRUCTIONS:
	// - In FileMaker Pro open the OpenSSL.fmp12 example.
	// - Go to the tab: "encrypt for PHP OpenSSL".
	// - Encrypt some data.
	// - Export the data from FileMaker (use the button : Export to desktop)
	// 
	// - Install php7 (if not installed already).
	//   This script was tested with: PHP 7.1.23 (cli) (built: Nov  7 2018 18:20:35)
	//   Note that the OpenSSL functions may also work with PHP 5.5 and later (we have not tested this).

	// - Place this php example script on your Desktop.
	// - Open terminal.app
	// - Run this php script with:
	//		"php -f <path to the php file>"
	//   so if you have not renamed this example file it will be:
	//		"php -f ~/Desktop/php7-decrypt-from-encryptor-AES256.php"  (without the quotes)
	//
	// You can tweak some of the variables to vary the output you get.
	//
    echo "\n------------------------------------------------------\n";
    echo "TROI test of Troi Encryptor Plug-in 6.0 generated data \n";
    echo "------------------------------------------------------\n";
    echo "Using as input a text file, which must be encrypted with the Encr_EncryptAES function of Troi Encryptor 6.\n";
    echo "\n";

	// ------------------------------------------------
	// INIT
	// ------------------------------------------------
	// first set the cipher variant we use and settings for the hash

	$cipher 	= 'AES-256-CBC';
	$blockSize 	= 16;
	$keySize 	= 32;

	$hash_algo 			= 'sha1';
	$hash_len   		= 20;
	$hash_iterations 	= 10000;
	
	// In OpenSSL the encrypted string starts with "Salted__" + 8 bytes salt
	$Salted__Str 		= 'Salted__';
	$Salted__StrLen 	= strlen($Salted__Str); // = 8
	$saltLen 			= 8;

	// ------------------------------------------------
	$Encrypted_data_FileName = 'For_OpenSSL_Encrypted_data.txt';
	$Extra_info_FileName      = 'For_OpenSSL_Encrypted_info.txt';
	// ------------------------------------------------

	// Calc the path to the users home folder:
	$home_path = getenv('HOME'); // if this does not work, fill in next line
	// for macOS it will be like:
	// 		$home_path = '/Users/YOUR_USER_NAME';
	// for Windows it will be like:
	//		$home_path = 'C:/Users/YOUR_USER_NAME';


	// First get the file with the Encrypted_data:
	$InFileDataPath = 	$home_path.'/Desktop/'.$Encrypted_data_FileName;
	if(!file_exists($InFileDataPath)) {
	    echo "Cannot open the data file. Stopping.\n";
		exit(-47);
	}

	// Get the file with the extra Encrypted_info.
	//
	// This info also contains the password and the key: for testing only!!!
	// NEVER ADD THIS IN REAL USES!!!
	// in real applications the receiving party will have either the password or the key.

	$InFileExtraInfoPath = 	$home_path.'/Desktop/'.$Extra_info_FileName;
	

	// Get extra info file content as string
  	if(file_exists($InFileExtraInfoPath))
  	{
		$InFileExtraInfo = file_get_contents($InFileExtraInfoPath);
		$ExtraInfoLen = strlen($InFileExtraInfo); // get string length
	}
	else
		$ExtraInfoLen = 0;

	if($ExtraInfoLen > 0 )
	{
	    echo "Found the extra info file.\n";
	    echo "NOTE This also contains the password, for testing only: NEVER ADD THIS IN REAL IMPLEMENTATIONS!\n\n";

		// Extract info from the extra info file: //
		$searchstr = 'Initialization vector: "';
		$pos = strpos($InFileExtraInfo, $searchstr);
		$ivBase64 = substr($InFileExtraInfo, $pos+strlen($searchstr), strpos($InFileExtraInfo, '"', $pos+strlen($searchstr)) - $pos - strlen($searchstr));
		//
		$searchstr = 'Password used: "';
		$pos = strpos($InFileExtraInfo, $searchstr);
		$password = substr($InFileExtraInfo, $pos+strlen($searchstr), strpos($InFileExtraInfo, '"', $pos+strlen($searchstr)) - $pos - strlen($searchstr));
		//
		$searchstr = 'Salt used: "';
		$pos = strpos($InFileExtraInfo, $searchstr);
		$saltHex = substr($InFileExtraInfo, $pos+strlen($searchstr), strpos($InFileExtraInfo, '"', $pos+strlen($searchstr)) - $pos - strlen($searchstr));
		echo "Imported: iv (Base64) = '" . trim($ivBase64) . "'\n";
		echo "Imported: password = '" .    trim($password) . "'\n";
		echo "Imported: salt (hex) = '" .  trim($saltHex) . "'\n";
		$useOwnPassword = 1;
  	}
  	else
  	{
		// Extra info file not found: you have to fill this in manually:
		// fill in your key etc. as used in the FileMaker example here:
		$keyBase64 				= '<your EncryptionKey here>';  // KEEP Secret!!
		$ivBase64 				= '<your InitializationVector here>';  // change every time
		$saltHex 			    = '<your Salt here>'; // in hex format

		$useOwnPassword 		= 0;
		if($useOwnPassword)
			$password = 'very secret key';
		else
			$password = '';
		$key = base64_decode($keyBase64);
  	}
	
	$salt = Hex2Bin($saltHex);

	// get data file content as string
	$InFileBase64 	= file_get_contents($InFileDataPath);
  	$InFileData 	= base64_decode($InFileBase64);
   	// get string length
	$FileLen = strlen($InFileBase64);
	echo "\nFound the data file. \n";
   	echo "File path = " . trim($InFileDataPath) . "\n";
   	echo "File len = "  . trim($FileLen) . "\n";
	if($FileLen == 0)
	{
	 	exit;
	}
	
    $InFileBase64Clean = str_replace("\r", "\n", $InFileBase64);
   	echo "File data (Base64) = \n" . trim($InFileBase64Clean) . "\n";
    echo "\n";



// ------------------------------------------------
	echo "Determine the key to use.\n";
// ------------------------------------------------

	$ivSize = openssl_cipher_iv_length($cipher);

    if($useOwnPassword)
    {
		echo "We use the supplied password and the salt to generate the key.\n";
		// Create the key
		echo "Generating the key with pbkdf2 and iterations = " . $hash_iterations . "\n";

		$key = openssl_pbkdf2($password, $salt, $keySize, $hash_iterations, $hash_algo);
		$keyBase64 = base64_encode($key);
    }
    
 	echo "   Using Key (Base64) = " . trim($keyBase64) . "\n";
 	//$keyHex= bin2hex($key);
 	//echo "   Used Key (hex) = " . trim($keyHex) . "\n";
 	echo "   Using IV (Base64) = " . trim($ivBase64) . "\n";
  	echo "   Block size = " . trim($blockSize) . "\n";
  	echo "   IV size = " . trim($ivSize) . "\n";
  	echo "   Key size = " . trim($keySize) . "\n";

   	$iv  = base64_decode($ivBase64);
	
	// ------------------------------------------------
		echo "\nHandling salt.\n";
	// ------------------------------------------------
	$ciphertext64 = $InFileBase64;

	// Remove the salt at the beginning:
	$ciphertext_salted = base64_decode($ciphertext64);

	$saltOpenSSLformat = substr($ciphertext_salted, 0, $Salted__StrLen + $saltLen);
	//echo "Salt openSSLformat = " . $saltOpenSSLformat . "\n";
	$saltFromCiphertext = substr($saltOpenSSLformat, $Salted__StrLen, $saltLen);
	//echo "   Salt in ciphertext = " . $saltFromCiphertext . "\n";
	echo "   Salt in ciphertext (hex) = " . bin2hex($saltFromCiphertext) . "\n";

	// Remove the salted string and the salt:
	$ciphertext = substr($ciphertext_salted, $Salted__StrLen + $saltLen);
	//echo "ciphertext ex-salt = " . $ciphertext . "\n";

	// ------------------------------------------------
		echo "\nDecrypting the data now.\n";
	// ------------------------------------------------

	// We will use the salt derived from the ciphertext. This should be the same as the salt supplied in the extra info file.
	$salt = $saltFromCiphertext;

	// Decrypting here:
	$decrypted = openssl_decrypt($ciphertext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);

	//echo "Decrypted  = " . trim($decrypted) . "\n\n";
    $clean_decrypted = str_replace("\r", "\n", $decrypted); // replace \r of FMP with \n
	echo "The decrypted data (clean): \n";
    echo "------------------------------------------------------\n";
   	echo trim($clean_decrypted);
    echo "\n------------------------------------------------------\n";
	echo "End of script\n\n";

	exit(0);


?>
