+ Started implementing the file encryption

+ File encryption
This commit is contained in:
Daniel Legt 2021-02-28 13:34:12 +02:00
parent e2e770dcfe
commit a5923c43e4
3 changed files with 200 additions and 70 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
config.inc.php config.inc.php
example.enc.php
example.dec.php

26
example-file.php Normal file
View File

@ -0,0 +1,26 @@
<?php
require("./lib.php");
/**
* This is a simple example of how to encrypt files with the library
* The following code will read the file in chunks instead of loading
* the whole thing in memory, trying to keep the "Peak Memory Usage"
* as low as possible.
*/
define("INPUT_FILE", "./example.php");
define("OUTPUT_FILE", "./example.enc.php");
define("DEC_OUTPUT_FILE", "./example.dec.php");
// Initialize the class
$lib = new kpcrypt();
// Encrypt the file
$lib->encryptFile(INPUT_FILE, OUTPUT_FILE);
// Decrypt the file as well
$lib->encryptFile(OUTPUT_FILE, DEC_OUTPUT_FILE);
echo "Errors: \n";
print_r($lib->getErrors())

240
lib.php
View File

@ -14,6 +14,17 @@ class kpcrypt {
// The key to use in the encryption process // The key to use in the encryption process
private $key = null; 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 * @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. * Get the encryption blocks for files
* @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) { public function getEncryptionBlocks() {
// Grab the key from self-reference return $this->blocks;
$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;
}
} }
/** /**
* @param string $data The data to be encrypted, this can only encrypt strings. * Redefine the encryption blocks size
* @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') { public function setEncryptionBlocks(int $size = 10000) {
// Grab the key from self-reference // Make sure the size has a minimum of blocks read.
$key = $this->key; if ( $size < 1 ) $size = 1;
// Lowercase the cipher // Set the local blocks
$cipherMethod = strtolower($cipherMethod); $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;
}
// Check if the encryption method is valid // To encrypt a string
if (!in_array($cipherMethod, openssl_get_cipher_methods())) { $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipherMethod));
// Cypher was not in the available ciphers list.
return FALSE; // 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 // Lowercase the cipher
$iv_length = openssl_cipher_iv_length($cipherMethod); $cipherMethod = strtolower($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 // Check if the encryption method is valid
return $data; 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
} }