Skip to content

Instantly share code, notes, and snippets.

@aaronhurt
Last active May 7, 2016 00:24
Show Gist options
  • Save aaronhurt/aa7caee4b756328ac4d6 to your computer and use it in GitHub Desktop.
Save aaronhurt/aa7caee4b756328ac4d6 to your computer and use it in GitHub Desktop.
<?php
/**
* Example with all methods and default keys:
*
* $crypt = new phpCrypt;
*
* $crypt->cipher = "blowfish";
* printf("crypted == %s\ndecrypted == %s\n\n", ($crypted = $crypt->encrypt("hello world")), $crypt->decrypt($crypted));
*
* $crypt->cipher = "xor";
* printf("crypted == %s\ndecrypted == %s\n\n", ($crypted = $crypt->encrypt("hello world")), $crypt->decrypt($crypted));
*
* $crypt->cipher = null;
* printf("crypted == %s\ndecrypted == %s\n\n", ($crypted = $crypt->encrypt("hello world")), $crypt->decrypt($crypted));
*
* Outputs:
*
* crypted == E2wYAdbwbQBn%2B%2B2Fz0Z9ew%3D%3D
* decrypted == hello world
*
* crypted == BRwPHg5aDl5EDh0%3D
* decrypted == hello world
*
* crypted == aGVsbG8gd29ybGQ%3D
* decrypted == hello world
*
* Example compatible with command line ssl:
*
* $crypt = new phpCrypt(array('urlcode' => false));
*
* var_dump($crypt->keys());
* printf("crypted == %s\ndecrypted == %s", ($crypted = $crypt->encrypt("hello world")), $crypt->decrypt($crypted));
*
* Outputs:
*
* object(stdClass)#2 (4) {
* ["binkey"]=>
* string(16) "mycrazy16bytekey"
* ["hexkey"]=>
* string(32) "6D796372617A793136627974656B6579"
* ["biniv"]=>
* string(8) "e2f4ebc6"
* ["hexiv"]=>
* string(16) "6532663465626336"
* }
* crypted == E2wYAdbwbQBn++2Fz0Z9ew==
*
* Example shell command:
*
* somehost:$ printf "hello world" | openssl enc -blowfish -K 6D796372617A793136627974656B6579 -iv 6532663465626336|base64
* E2wYAdbwbQBn++2Fz0Z9ew==
*/
/**
* PHP Encryption class with output compatability with openssl cli tools
*/
class phpCrypt {
/**
* block size for padding/unpadding strings
* @var integer
*/
public $blocksize = 8;
/**
* the cipher to use (aes, blowfish, xor or null)
* @var string
*/
public $cipher = 'aes';
/**
* the encryption key
* @var string
*/
public $key = 'mycrazy16bytekey';
/**
* optional hex iv
* @var string
*/
public $hexiv = null;
/**
* optional hex key
* @var string
*/
public $hexkey = null;
/**
* urlencode/urldecode all output/input strings
* @var boolean
*/
public $urlcode = true;
/**
* base64encode/base64decode all output/input strings
* @var boolean
*/
public $base64code = true;
/**
* phpCrypt class constructor
* @param array $phpCryptParams array of initialization properties
*/
public function __construct(array $phpCryptParams = array()) {
foreach ($phpCryptParams as $key => $val) {
if (property_exists($this, $key)) {
$this->$key = $val;
}
}
}
/**
* XOR strings with keys for pseudo encryption
* @param string $string plain text input string
* @param string $key key value (optional)
* @return string thd xor'd string
*/
public function sxor($string, $key = null) {
/* check key */
if ($key === null) $key = $this->key;
/* init arrays */
$output = array();
$input = str_split($string);
$key = str_split($key);
/* get lengths */
$input_count = count($input);
$key_count = count($key);
/* xor string with key */
for ($i = 0, $k = 0; $i < $input_count; $i++) {
$output[$i] = $input[$i] ^ $key[$k];
/* get next key - loop if needed */
$k = (($k + 1) >= $key_count) ? 0 : ($k + 1);
}
/* return joined output */
return join('', $output);
}
/**
* Add PKCS5 block padding to string
* @param string $string the string to pad
* @param integer $blocksize block size/length in bytes (optional)
* @return string the padded string
*/
public function pad($string, $blocksize = null) {
/* check blocksize */
if ($blocksize === null) $blocksize = $this->blocksize;
/* original string length */
$slength = strlen($string);
/* the padding */
$padding = ($blocksize - ($slength % $blocksize));
/* return padded string */
return str_pad($string, ($slength + $padding), chr($padding));
}
/**
* Removes PKCS5 block padding from string
* @param string $string the padded string
* @return string the unpadded string
* @throws Exception on corrupt strings
*/
public function unpad($string) {
/* padded string length */
$slength = strlen($string);
/* the padding */
$padding = ord(substr($string, -1));
/* check lengths */
if ($padding > $slength) {
/* bad lengths */
throw new Exception('corrupt pkcs5 string - padding length greater than string length');
}
/* check padding */
if (strspn($string, chr($padding), ($slength - $padding)) !== $padding) {
/* padding doesn't match */
throw new Exception('corrupt pkcs5 string - padding does not match');
}
/* looks good ... return string minus padding */
return substr($string, 0, ($slength - $padding));
}
/**
* Generate compliant encryption keys and init vectors for CBC methods
* @param string $key the encryption key (optional)
* @param integer $keysize final byte length of the encryption key (optional)
* @param integer $ivsize final byte length of the init vector (optional)
* @return object object containing strings: binkey, hexkey, biniv, hexiv
*/
public function keys($key = null, $keysize, $ivsize) {
/* check key */
if ($key === null) $key = $this->key;
/* init return object */
$retval = new stdClass();
/* generate the bin key */
if ($this->hexkey !== null) {
/* set hex key as is */
$retval->hexkey = $this->hexkey;
/* decode passed hex for bin */
$retval->binkey = hex2bin($this->hexkey);
} else {
/* generate key */
$retval->binkey = substr(str_pad($key, $keysize, "\0"), 0, $keysize);
/* encode hex key */
$retval->hexkey = strtoupper(bin2hex($retval->binkey));
}
/* check for hex iv */
if ($this->hexiv !== null) {
/* set hex iv as is */
$retval->hexiv = $this->hexiv;
/* decode hex for bin */
$retval->biniv = hex2bin($this->hexiv);
} else {
/* check passed key */
if (strlen($key)) {
/* generate bin vector from key hash */
$retval->biniv = substr(md5($key), 0, $ivsize);
} else {
/* make null vector */
$retval->biniv = str_pad("", $ivsize, "\0");
}
/* encode hex vector */
$retval->hexiv = strtoupper(bin2hex($retval->biniv));
}
/* return the object */
return $retval;
}
/**
* Encrypt and encode strings for general use
* @param string $plain plain text string to be encrypted
* @throws Exception on missing builtin functions
* @return string the encrypted/encoded string
*/
public function encrypt($plain) {
/* switch based on type */
switch(strtolower($this->cipher)) {
case "xor":
/* xor plain with key */
$output = $this->sxor($plain);
break;
case "aes" :
/* check for function and constant */
if (!function_exists('mcrypt_decrypt') || !constant("MCRYPT_RIJNDAEL_128")) {
/* throw exception - nothing else we can do */
throw new Exception('missing mcrypt function or constant');
}
/* generate key and init vector */
$cbc = $this->keys($this->key, 16, 16);
/* encrypt the string with pkcs5 padding */
$output = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $cbc->binkey, $this->pad($plain),
MCRYPT_MODE_CBC, $cbc->biniv);
break;
case "blowfish" :
/* check for function and constant */
if (!function_exists('mcrypt_decrypt') || !constant("MCRYPT_BLOWFISH")) {
/* throw exception - nothing else we can do */
throw new Exception('missing mcrypt function or constant');
}
/* generate key and init vector */
$cbc = $this->keys($this->key, 16, 8);
/* encrypt the string with pkcs5 padding */
$output = mcrypt_encrypt(MCRYPT_BLOWFISH, $cbc->binkey, $this->pad($plain),
MCRYPT_MODE_CBC, $cbc->biniv);
break;
default:
/* use plain as output */
$output = $plain;
break;
}
/* base64 encode */
if ($this->base64code === true) {
$output = base64_encode($output);
}
/* url encode */
if ($this->urlcode === true) {
$output = urlencode($output);
}
/* return */
return $output;
}
/**
* Decode and decrypt strings for general use
* @param string $crypted string to be decrypted
* @throws Exception on missing builtin functions
* @return string the decoded/decrypted string
*/
public function decrypt($crypted) {
/* url decode */
if ($this->urlcode === true) {
$crypted = urldecode($crypted);
}
/* base64 decode */
if ($this->base64code === true) {
$crypted = base64_decode($crypted);
}
/* switch based on type */
switch(strtolower($this->cipher)) {
case "xor" :
/* xor crypted with key */
$plain = $this->sxor($crypted);
break;
case "aes" :
/* check for function and constant */
if (!function_exists('mcrypt_decrypt') || !constant("MCRYPT_RIJNDAEL_128")) {
/* throw exception - nothing else we can do */
throw new Exception('missing mcrypt function or constant');
}
/* generate key and init vector */
$cbc = $this->keys($this->key, 16, 16);
/* encrypt the string with pkcs5 padding */
$plain = $this->unpad(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $cbc->binkey, $crypted,
MCRYPT_MODE_CBC, $cbc->biniv));
break;
case "blowfish" :
/* check for function and constant */
if (!function_exists('mcrypt_decrypt') || !constant("MCRYPT_BLOWFISH")) {
/* throw exception - nothing else we can do */
throw new Exception('missing mcrypt function or constant');
}
/* generate key and init vector */
$cbc = $this->keys($this->key, 16, 8);
/* encrypt the string with pkcs5 padding */
$plain = $this->unpad(mcrypt_decrypt(MCRYPT_BLOWFISH, $cbc->binkey, $crypted,
MCRYPT_MODE_CBC, $cbc->biniv));
break;
default:
/* use plain as output */
$plain = $crypted;
break;
}
/* return */
return $plain;
}
}
#!/usr/bin/env php
<?php
/* only run from the cli */
if (php_sapi_name() !== 'cli') {
die('This script may only be run from the command line.' . "\n");
}
/* check arguments */
if ($argc < 5) {
die('Usage: ' . $argv[0] . ' <encrypt|decrypt> <hex key> <hex iv> <string>' . "\n");
}
/* pull in functions */
require_once(realpath(dirname(__FILE__)) . '/php-crypt.php');
/* build and setup object */
$crypt = new phpCrypt;
$crypt->cipher = "aes";
$crypt->key = null;
$crypt->hexkey = $argv[2];
$crypt->hexiv = $argv[3];
$crypt->urlcode = false;
/* prep text */
$text = str_replace(array('-', '_'), array('+', '/'), $argv[4]);
/* switch based on command */
switch(strtolower($argv[1])) {
case 'encrypt':
printf("%s\n", $crypt->encrypt($text));
break;
case 'decrypt':
printf("%s\n", $crypt->decrypt($text));
break;
}
/* exit clean */
exit(0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment