Skip to content

Instantly share code, notes, and snippets.

@dachande
Created April 26, 2016 07:27
Show Gist options
  • Save dachande/b290fcd0a6cc8265971ce0a6156586c2 to your computer and use it in GitHub Desktop.
Save dachande/b290fcd0a6cc8265971ce0a6156586c2 to your computer and use it in GitHub Desktop.
Wrapper library for encryption and decryption of any kind of data using mcrypt.
<?php
/**
* Krypton.php
*
* This is a wrapper library for encryption and decryption of
* any kind of data using mcrypt.
*
* The library uses Blowfish in CBC mode.
*
* @license GPL
* @author Daniel Schultheis <d.schultheis@kabel-salat.net>
* @category Encryption
* @package Krypton
*/
class Krypton extends Object {
/**
* Mcrypt initialization error on incorrect key length
*/
const INIT_ERROR_INCORRECT_KEY_LENGTH = -3;
/**
* Mcrypt initialization error on memory allocation
*/
const INIT_ERROR_MEMORY_ALLOCATION = -4;
/**
* Encryption descriptor
*
* @var reference|null
*/
private $cryptor = null;
/**
* Encryption/Decryption key
*
* @var string
*/
private $key = '';
/**
* Initialization vector (IV)
*
* @var string|null
*/
private $iv = null;
/**
* Initialized the encryption module and sets the key
*
* @param string $key
* @return void
*/
public function __construct($key) {
$this->cryptor = mcrypt_module_open(MCRYPT_BLOWFISH, "", MCRYPT_MODE_CBC, "");
$this->key = $key;
}
/**
* De-initialized the encryption module
*
* @return void
*/
public function __destruct() {
mcrypt_module_close($this->cryptor);
}
/**
* Manually sets an initialization vector (IV)
*
* @param string $iv
* @return void
*/
public function setIV($iv) {
if (preg_match('/^[0-9a-f]+$/', $iv)) {
$this->iv = self::hex2bin($iv);
} else {
$this->iv = $iv;
}
}
/**
* Get the initialization vector (IV)
*
* @return string
*/
public function getIV() {
return bin2hex($this->iv);
}
/**
* Generates a random initialization vector (IV)
*
* @return string|void
*/
public function generateIV($returnIV = false) {
if (PHP_OS == 'WIN32' || PHP_OS == 'WINNT' || PHP_OS == 'Windows') {
$random_dev = MCRYPT_RAND;
}
else {
$random_dev = MCRYPT_DEV_URANDOM;
}
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->cryptor), $random_dev);
$this->iv = $iv;
if ($returnIV)
return $this->getIV();
}
/**
* Encrypt data
*
* @param mixed $data
* @param int &$errornum
* @param string &$errormsg
* @return string|null
*/
public function encrypt($data, &$errornum, &$errormsg) {
// Generate IV if not yet set
if ($this->iv == null) $this->generateIV();
// Initialize mcrypt
$this->_mcrypt_init($errornum, $errormsg);
if ($errornum < 0 || $errornum === FALSE) {
$this->_mcrypt_deinit();
return null;
}
// Encrypt
$encrypted = @mcrypt_generic($this->cryptor, $data);
$this->_mcrypt_deinit();
return $encrypted;
}
/**
* Decrypt data
*
* @param mixed $data
* @param int &$errornum
* @param string &$errormsg
* @return string
*/
public function decrypt($data, &$errornum, &$errormsg) {
if ($this->iv == null) return null;
// Initialize mcrypt
$this->_mcrypt_init($errornum, $errormsg);
if ($errornum < 0 || $errornum === FALSE) {
$this->_mcrypt_deinit();
return null;
}
// Decrypt
$decrypted = @mdecrypt_generic($this->cryptor, $data);
$this->_mcrypt_deinit();
return $decrypted;
}
/**
* Initialize all buffers needed for encryption
*
* @param int &$errornum
* @param string &$errormsg
* @return void
*/
private function _mcrypt_init(&$errornum, &$errormsg) {
$initErrorStr = '';
// Initialize mcrypt
$initError = @mcrypt_generic_init($this->cryptor, $this->key, $this->iv);
// Check if an error occured
if ($initError < 0 || $initError === FALSE) {
switch ($initError) {
case self::INIT_ERROR_MEMORY_ALLOCATION:
$initErrorStr = 'Memory allocation error';
break;
case self::INIT_ERROR_INCORRECT_KEY_LENGTH:
$initErrorStr = 'Incorrect key length';
break;
case FALSE:
$initErrorStr = 'Incorrect parameter passed for initialization';
break;
default:
$initErrorStr = 'Unknown error while initializing mcrypt module';
}
}
$errornum = $initError;
$errormsg = $initErrorStr;
}
/**
* De-initialize encryption module
*
* @return bool
*/
private function _mcrypt_deinit() {
return mcrypt_generic_deinit($this->cryptor);
}
/**
* Converts hex to bin
*
* @param string $data
* @return string
*/
public static function hex2bin($data) {
$bin = "";
$i = 0;
do {
$bin .= chr(hexdec($data{$i}.$data{($i + 1)}));
$i += 2;
} while ($i < strlen($data));
return $bin;
}
/**
* Encode string for securely transmitting it as an URL GET-Parameter
*
* @param string $data
* @param bool $use_rawurlencode
* @return string
*/
public static function encode($data, $use_rawurlencode=true) {
return ($use_rawurlencode) ? rawurlencode(base64_encode($data)) : base64_encode($data);
}
/**
* Decode a previously encoded string
*
* @param string $data
* @param bool $use_rawurldecode
* @return string
*/
public static function decode($data, $use_rawurldecode=true) {
return ($use_rawurldecode) ? base64_decode(rawurldecode($data)) : base64_decode($data);
}
/**
* Generates and returns checksum using SHA256 as default hash algorithm.
*
* The data array used for hashing is sorted by keys and serialized before hash generation.
* The checksum is automatically appended to the data array. You can prevent this
* behaviour by calling this method with $chksumAdd=false
*
* @param array &$data
* @param boolean $chksumAdd
* @param string $algo
* @return string
*/
public static function generateChecksum(&$data, $chksumAdd=true, $chksumKey='chksum', $algo='sha256') {
ksort($data);
$chksum = hash($algo, serialize($data));
// Add checksum to data array
if ($chksumAdd) {
$data[$chksumKey] = $chksum;
}
return $chksum;
}
/**
* Checksum validation using SHA256 as default hash algorithm,
*
* The checksum is taken from the supplied data array with the default key 'chksum'.
* You can specify a different key if needed.
* The checksum is automatically stripped from the data array. You can prevent that
* behaviour by calling this method with $chksumStrip=false
*
* @param array $data
* @param boolean $chksumStrip
* @param string $chksumKey
* @param string $algo
* @return boolean
*/
public static function validateChecksum(&$data, $chksumStrip=true, $chksumKey='chksum', $algo='sha256') {
if (!is_array($data)) return false;
// Get checksum, remove from data and sort array
$chksum = $data[$chksumKey];
// Make a copy of the data array and remove checksum.
$dataCopy = $data;
unset($dataCopy[$chksumKey]);
// Remove checksum from data array
if ($chksumStrip) unset($data[$chksumKey]);
// Validate
ksort($dataCopy);
return ($chksum == hash($algo, serialize($dataCopy))) ? true : false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment