2021-02-27 13:37:09 +02:00
<? php
2021-02-28 10:58:55 +02:00
2021-02-27 13:37:09 +02:00
/**
2021-02-28 10:58:55 +02:00
* @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.
*
2021-02-27 13:37:09 +02:00
*/
2021-02-28 10:58:55 +02:00
class kpcrypt {
2021-02-27 13:37:09 +02:00
2021-02-28 10:58:55 +02:00
// The key to use in the encryption process
private $key = null ;
2021-02-27 13:37:09 +02:00
2021-02-28 13:34:12 +02:00
/**
* 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 = [];
2021-02-28 10:58:55 +02:00
/**
* @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" ));
}
2021-02-28 11:07:51 +02:00
$this -> key = $key ;
2021-02-27 13:37:09 +02:00
}
2021-02-28 10:58:55 +02:00
/**
* 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 ;
}
2021-02-27 13:37:09 +02:00
2021-02-28 10:58:55 +02:00
/**
2021-02-28 13:34:12 +02:00
* Get the encryption blocks for files
2021-02-28 10:58:55 +02:00
*/
2021-02-28 13:34:12 +02:00
public function getEncryptionBlocks () {
return $this -> blocks ;
2021-02-27 13:37:09 +02:00
}
2021-02-28 10:58:55 +02:00
/**
2021-02-28 13:34:12 +02:00
* Redefine the encryption blocks size
2021-02-28 10:58:55 +02:00
*/
2021-02-28 13:34:12 +02:00
public function setEncryptionBlocks ( int $size = 10000 ) {
// Make sure the size has a minimum of blocks read.
if ( $size < 1 ) $size = 1 ;
2021-02-28 10:58:55 +02:00
2021-02-28 13:34:12 +02:00
// Set the local blocks
$this -> blocks = $size ;
}
2021-02-28 10:58:55 +02:00
2021-02-28 13:34:12 +02:00
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 ;
}
2021-02-28 10:58:55 +02:00
}
2021-02-28 13:34:12 +02:00
/**
* @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 ;
2021-02-28 10:58:55 +02:00
2021-02-28 13:34:12 +02:00
// Lowercase the cipher
$cipherMethod = strtolower ( $cipherMethod );
2021-02-28 10:58:55 +02:00
2021-02-28 13:34:12 +02:00
// 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 ;
}
2021-02-28 10:58:55 +02:00
2021-02-28 13:34:12 +02:00
// 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
2021-02-28 10:58:55 +02:00
2021-02-27 13:37:09 +02:00
}