225 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
<?php
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Kato Twofold
 | 
						|
 * @copyright MIT
 | 
						|
 * 
 | 
						|
 * The class has full support for encryption of strings, provides validation for those
 | 
						|
 * and makes sure they can be decrypted on the other end, the key is extremely important
 | 
						|
 * and you MUST keep track of it and not lose it as there is no way of getting it back.
 | 
						|
 * 
 | 
						|
 */
 | 
						|
class kpcrypt {
 | 
						|
 | 
						|
    // The key to use in the encryption process
 | 
						|
    private $key = null;
 | 
						|
 | 
						|
    /**
 | 
						|
    * Define the number of blocks that should be read from the source file for each chunk.
 | 
						|
    * For 'AES-128-CBC' each block consist of 16 bytes.
 | 
						|
    * So if we read 10,000 blocks we load 160kb into memory. You may adjust this value
 | 
						|
    * to read/write shorter or longer chunks.
 | 
						|
    */
 | 
						|
    private $blocks = 10000;
 | 
						|
 | 
						|
    // A log of all of the errors, rather nice for debugging
 | 
						|
    private $errorLog = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $key [Optional] The key to use for encryption, if none is mentioned a random one will be generated
 | 
						|
     */
 | 
						|
    public function __construct( string $key = null) {
 | 
						|
        // If no key is mentioned, generate one
 | 
						|
        if ( empty($key) ) {
 | 
						|
            $key = bin2hex(openssl_random_pseudo_bytes("64"));
 | 
						|
        }
 | 
						|
 | 
						|
        $this->key = $key;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the key that the instance is currently using, really useful for when you randomly generate it!
 | 
						|
     * @return string The key of the instance
 | 
						|
     */
 | 
						|
    public function getKey() {
 | 
						|
        return $this->key;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the encryption blocks for files
 | 
						|
     */
 | 
						|
    public function getEncryptionBlocks() {
 | 
						|
        return $this->blocks;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Redefine the encryption blocks size
 | 
						|
     */
 | 
						|
    public function setEncryptionBlocks(int $size = 10000) {
 | 
						|
        // Make sure the size has a minimum of blocks read.
 | 
						|
        if ( $size < 1 ) $size = 1;
 | 
						|
 | 
						|
        // Set the local blocks
 | 
						|
        $this->blocks = $size;
 | 
						|
    }
 | 
						|
 | 
						|
    public function getErrors() {
 | 
						|
        return $this->errorLog;
 | 
						|
    }
 | 
						|
 | 
						|
    // #region String Encryption
 | 
						|
 | 
						|
        /**
 | 
						|
         * @param string $data The data to be encrypted, this can only encrypt strings.
 | 
						|
         * @param string $cipherMethod The cypher method to use in the encryption process, these can be checked using 
 | 
						|
         * @param bool $integrity_check Check if the encrypted data can also be decypted, this will take 2x more time to process the data, but will make 100% sure that the data is safe and can be decrypted.
 | 
						|
         */
 | 
						|
        function encryptData(string $data, string $cipherMethod = 'AES-256-CBC', bool $integrity_check = TRUE) {
 | 
						|
            // Grab the key from self-reference
 | 
						|
            $key = $this->key;
 | 
						|
 | 
						|
            // Lowercase the cipher
 | 
						|
            $cipherMethod = strtolower($cipherMethod);
 | 
						|
 | 
						|
            // Check if the encryption method is valid
 | 
						|
            if (!in_array($cipherMethod, openssl_get_cipher_methods())) {
 | 
						|
                // Cypher was not in the available ciphers list.
 | 
						|
                $this->errorLog[] = "[" . __LINE__ . "]" . $cipherMethod . " isn't a valid cipherMethod.";
 | 
						|
                return FALSE;
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
            // To encrypt a string   
 | 
						|
            $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipherMethod));
 | 
						|
 | 
						|
            // Encrypt the data
 | 
						|
            $encryptedData = openssl_encrypt($data, $cipherMethod, $key, OPENSSL_RAW_DATA, $iv);
 | 
						|
 | 
						|
            // Append the iv to the encrypted data
 | 
						|
            $encryptedData = $iv . $encryptedData;
 | 
						|
 | 
						|
            // base64 encrypt to make sure we don't lose bytes
 | 
						|
            $encryptedData = base64_encode($encryptedData);
 | 
						|
 | 
						|
            // Check if we should verify the integrity of the encryption
 | 
						|
            if ($integrity_check === TRUE) {
 | 
						|
                // Test for decryption validity
 | 
						|
                if (md5($this->decryptData($encryptedData, $cipherMethod)) === md5($data)) {
 | 
						|
                    // Put the output in the result
 | 
						|
                    return $encryptedData;
 | 
						|
                } else {
 | 
						|
                    // Assign the output to the result
 | 
						|
                    $this->errorLog[] = "[" . __LINE__ . "]" . "Failed integrity check";
 | 
						|
                    return FALSE;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                // Simply return the results
 | 
						|
                return $encryptedData;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * @param string $data The data to be encrypted, this can only encrypt strings.
 | 
						|
         * @param string $cipherMethod The cypher method to use in the encryption process, these can be checked using 
 | 
						|
         */
 | 
						|
        function decryptData(string $data, string $cipherMethod = 'AES-256-CBC') {
 | 
						|
            // Grab the key from self-reference
 | 
						|
            $key = $this->key;
 | 
						|
 | 
						|
            // Lowercase the cipher
 | 
						|
            $cipherMethod = strtolower($cipherMethod);
 | 
						|
 | 
						|
            
 | 
						|
            // Check if the encryption method is valid
 | 
						|
            if (!in_array($cipherMethod, openssl_get_cipher_methods())) {
 | 
						|
                // Cypher was not in the available ciphers list.
 | 
						|
                $this->errorLog[] = "[" . __LINE__ . "]" . $cipherMethod . " isn't a valid cipherMethod.";
 | 
						|
                return FALSE;
 | 
						|
            }
 | 
						|
 | 
						|
            // base64 decode the data.
 | 
						|
            $data = base64_decode($data);
 | 
						|
 | 
						|
            // Get the length of the IV
 | 
						|
            $iv_length = openssl_cipher_iv_length($cipherMethod);
 | 
						|
            // Get the IV from the decoded data
 | 
						|
            $iv = substr($data, 0, $iv_length);
 | 
						|
 | 
						|
            // Get the encrypted string from the data
 | 
						|
            $data = substr($data, $iv_length);
 | 
						|
 | 
						|
            // Decrypt the data
 | 
						|
            $data = openssl_decrypt($data, $cipherMethod, $key, OPENSSL_RAW_DATA, $iv);
 | 
						|
            
 | 
						|
 | 
						|
            // Return the data
 | 
						|
            return $data;
 | 
						|
        }
 | 
						|
 | 
						|
    // #endregion
 | 
						|
 | 
						|
 | 
						|
    // #region File Encryption
 | 
						|
 | 
						|
        public function encryptFile(string $fileInput, string $fileOutput, string $cipherMethod = 'AES-256-CBC', bool $integrity_check = TRUE) {
 | 
						|
            // Lowercase the cipher
 | 
						|
            $cipherMethod = strtolower($cipherMethod);
 | 
						|
 | 
						|
            // Check if the encryption method is valid
 | 
						|
            if (!in_array($cipherMethod, openssl_get_cipher_methods())) {
 | 
						|
                // Cypher was not in the available ciphers list.
 | 
						|
                $this->errorLog[] = "[" . __LINE__ . "]" . $cipherMethod . " isn't a valid cipherMethod.";
 | 
						|
                return FALSE;
 | 
						|
            }
 | 
						|
 | 
						|
            // To encrypt a string   
 | 
						|
            $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipherMethod));
 | 
						|
 | 
						|
            // Try and open the destionation
 | 
						|
            if ( $fout = fopen($fileOutput, 'w') ) {
 | 
						|
                // Try and open the input file
 | 
						|
                if ($fin = fopen($fileInput, 'rb') ) {
 | 
						|
                    // Place the IV at the beginning of the file for later decryption
 | 
						|
                    fwrite($fout, $iv);
 | 
						|
 | 
						|
                    // Start reading from the input file
 | 
						|
                    while ( !feof($fin) ) {
 | 
						|
                        // Read in blocks of 16
 | 
						|
                        $plaintext = fread($fin, 16 * $this->blocks);
 | 
						|
                        $ciphertext = openssl_encrypt($plaintext, $cipherMethod, $this->key, OPENSSL_RAW_DATA, $iv);
 | 
						|
                        // Use the first 16 bytes of the ciphertext as the next initialization vector
 | 
						|
                        $iv = substr($ciphertext, 0, 16);
 | 
						|
                        fwrite($fout, $ciphertext);
 | 
						|
                    }
 | 
						|
 | 
						|
                    // Close the input file
 | 
						|
                    fclose($fin);
 | 
						|
 | 
						|
                } else {
 | 
						|
                    $this->errorLog[] = "[" . __LINE__ . "]" . "Could not open input file for reading.";
 | 
						|
                    // Close the output file
 | 
						|
                    fclose($fout);
 | 
						|
                    return false;
 | 
						|
                }
 | 
						|
 | 
						|
            } else {
 | 
						|
                $this->errorLog[] = "[" . __LINE__ . "]" . "Could not open file output path for writing.";
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
            // Close the output file
 | 
						|
            fclose($fout);
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
 | 
						|
        public function decryptFile(string $fileInput, string $fileOutput, string $cipherMethod = 'AES-256-CBC') {
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
    // #endregion
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 |