diff --git a/.gitignore b/.gitignore index 2b9ce0a..7e8cca8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -config.inc.php \ No newline at end of file +config.inc.php +example.enc.php +example.dec.php \ No newline at end of file diff --git a/example-file.php b/example-file.php new file mode 100644 index 0000000..4051288 --- /dev/null +++ b/example-file.php @@ -0,0 +1,26 @@ +encryptFile(INPUT_FILE, OUTPUT_FILE); + +// Decrypt the file as well +$lib->encryptFile(OUTPUT_FILE, DEC_OUTPUT_FILE); + +echo "Errors: \n"; +print_r($lib->getErrors()) diff --git a/lib.php b/lib.php index f7aa8c3..462d2cb 100644 --- a/lib.php +++ b/lib.php @@ -14,6 +14,17 @@ 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 */ @@ -35,88 +46,179 @@ class kpcrypt { } /** - * @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. + * Get the encryption blocks for files */ - 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. - 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 - return FALSE; - } - } else { - // Simply return the results - return $encryptedData; - } + public function getEncryptionBlocks() { + return $this->blocks; } /** - * @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 + * Redefine the encryption blocks size */ - function decryptData(string $data, string $cipherMethod = 'AES-256-CBC') { - // Grab the key from self-reference - $key = $this->key; + public function setEncryptionBlocks(int $size = 10000) { + // Make sure the size has a minimum of blocks read. + if ( $size < 1 ) $size = 1; - // Lowercase the cipher - $cipherMethod = strtolower($cipherMethod); + // Set the local blocks + $this->blocks = $size; + } - - // Check if the encryption method is valid - if (!in_array($cipherMethod, openssl_get_cipher_methods())) { - // Cypher was not in the available ciphers list. - return FALSE; + 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; + } } - // base64 decode the data. - $data = base64_decode($data); + /** + * @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; - // 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); + // Lowercase the cipher + $cipherMethod = strtolower($cipherMethod); - // Get the encrypted string from the data - $data = substr($data, $iv_length); + + // 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; + } - // Decrypt the data - $data = openssl_decrypt($data, $cipherMethod, $key, OPENSSL_RAW_DATA, $iv); - + // 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 - // Return the data - return $data; - } }