Last active
March 22, 2016 13:04
-
-
Save http403/39857700831591775b1c to your computer and use it in GitHub Desktop.
AES Encryption with Custom Block Cipher Mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AES Encryption with Custom Block Cipher Mode. | |
THIS BLOCK CIPHER MODE MAY HAVE POTENTIAL VULNERABILITY, DO NOT USE IN PRODUCTION PRODUCT. I code it ONLY FOR FUN AND TESTING PURPOSE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
interface Base62Interface { | |
public static function encode($data); | |
public static function decode($data); | |
} | |
Class Base62 implements Base62Interface { | |
/** | |
* @param $data | |
* @return string | |
*/ | |
public static function encode($data) { | |
$outstring = ''; | |
$l = strlen($data); | |
for ($i = 0; $i < $l; $i += 8) { | |
$chunk = substr($data, $i, 8); | |
$outlen = ceil((strlen($chunk) * 8)/6); //8bit/char in, 6bits/char out, round up | |
$x = bin2hex($chunk); //gmp won't convert from binary, so go via hex | |
$w = gmp_strval(gmp_init(ltrim($x, '0'), 16), 62); //gmp doesn't like leading 0s | |
$pad = str_pad($w, $outlen, '0', STR_PAD_LEFT); | |
$outstring .= $pad; | |
} | |
return $outstring; | |
} | |
/** | |
* @param $data | |
* @return string | |
*/ | |
public static function decode($data) { | |
$outstring = ''; | |
$l = strlen($data); | |
for ($i = 0; $i < $l; $i += 11) { | |
$chunk = substr($data, $i, 11); | |
$outlen = floor((strlen($chunk) * 6)/8); //6bit/char in, 8bits/char out, round down | |
$y = gmp_strval(gmp_init(ltrim($chunk, '0'), 62), 16); //gmp doesn't like leading 0s | |
$pad = str_pad($y, $outlen * 2, '0', STR_PAD_LEFT); //double output length as as we're going via hex (4bits/char) | |
$outstring .= pack('H*', $pad); //same as hex2bin | |
} | |
return $outstring; | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
interface CryptFunctionsInterface { | |
public static function signText($plaintext, $key); | |
public static function genSubKey($key, $salt); | |
} | |
class CryptFunctions implements CryptFunctionsInterface { | |
protected static function ivAdd($big_num_str, $to_add) { | |
$big_num = str_split(strrev($big_num_str)); | |
for ($i = 0; $i < count($big_num); $i++) { | |
$tmp = ord($big_num[$i]) + $to_add; | |
$big_num[$i] = $tmp % 256; | |
$to_add = floor( $tmp / 256 ); | |
} | |
while($to_add) { | |
$big_num[$i++] = $to_add % 256; | |
$to_add = floor( $to_add / 256 ); | |
} | |
for ($i = 0; $i < count($big_num); $i++) { | |
$big_num[$i] = chr($big_num[$i]); | |
} | |
return strrev(implode('', $big_num) ); | |
} | |
/** | |
* @return string | |
*/ | |
public static function genSafeRandomBytes($len) { | |
$cstrong = false; | |
while (!$cstrong) { | |
$bytes = openssl_random_pseudo_bytes($len, $cstrong); | |
} | |
return $bytes; | |
} | |
/** | |
* @param $iv | |
* @return bool|string | |
*/ | |
public static function genSubKey($key, $salt) { | |
return openssl_pbkdf2($key, $salt, 32, 50000, "SHA256"); | |
} | |
/** | |
* @param $plaintext | |
* @param $key | |
* @return string | |
*/ | |
public static function signText($plaintext, $key) { | |
return hash_hmac("sha512", $plaintext, $key, true); | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require "framework.CryptFunctions.class.php"; | |
require "framework.Base62.class.php"; | |
interface AESCustomInterface { | |
const CIPHER = "aes-256-ecb"; | |
public static function encrypt($key, $data); | |
public static function decrypt($key, $data); | |
} | |
class AESCustom extends CryptFunctions implements AESCustomInterface { | |
public static function encrypt($key, $data) { | |
$iv = parent::genSafeRandomBytes(16); | |
$nonce = parent::genSafeRandomBytes(16); | |
echo "First Block XOR\n"; | |
$firstBlock = self::strxor_direct($nonce, $iv); | |
$salt = parent::genSafeRandomBytes(16); | |
$hmac = parent::signText($data, $key); | |
$subkey = parent::genSubKey($key, $salt); | |
$data = self::pkcs7pad($data); | |
echo "HEX Data w/ Pad: " . bin2hex($data) . "\n"; | |
$tmp_r = base64_decode(openssl_encrypt($firstBlock, self::CIPHER, $subkey, OPENSSL_ZERO_PADDING)); | |
$result = ''; | |
for ($i = 0; $i < ceil(strlen($data) / 16); $i++) { | |
$tmp_n = parent::ivAdd($nonce, $i+1); | |
echo "TMP Nonce XOR\n"; | |
$tmp_n = self::strxor_direct($tmp_n, $tmp_r); | |
$tmp_x = base64_decode(openssl_encrypt($tmp_n, self::CIPHER, $subkey, OPENSSL_ZERO_PADDING)); | |
$tmp_d = substr($data, 16 * $i, 16); | |
echo "TMP Result XOR\n"; | |
echo "TMP X: " . bin2hex($tmp_x) . "\n"; | |
echo "TMP D: " . bin2hex($tmp_d) . "\n"; | |
$result .= $tmp_r = self::strxor_direct($tmp_x, $tmp_d); | |
} | |
echo "HEX Chiphertext: " . bin2hex($result) . "\n"; | |
return base64_encode($iv.$nonce.$salt.$hmac.$result); | |
//return bin2hex($result); | |
} | |
public static function decrypt($key, $data) { | |
$data = base64_decode($data); | |
$iv = substr($data, 0, 16); | |
$nonce = substr($data, 16, 16); | |
$salt = substr($data, 32, 16); | |
$hmac = substr($data, 48, strlen(parent::signText(null, null))); | |
$data = substr($data, 48 + strlen(parent::signText(null, null))); | |
$data = str_split($data, 16); | |
$subkey = parent::genSubKey($key, $salt); | |
$firstBlock = self::strxor_direct($nonce, $iv); | |
$tmp_r = base64_decode(openssl_encrypt($firstBlock, self::CIPHER, $subkey, OPENSSL_ZERO_PADDING)); | |
$result = ''; | |
for ($i = 0; $i < count($data); $i++) { | |
$tmp_n = parent::ivAdd($nonce, $i+1); | |
$tmp_n = self::strxor_direct($tmp_n, $tmp_r); | |
$tmp_x = base64_decode(openssl_encrypt($tmp_n, self::CIPHER, $subkey, OPENSSL_ZERO_PADDING)); | |
$result .= $tmp_r = self::strxor_direct($tmp_x, $data[$i]); | |
} | |
//return self::pkcs7unpad($result); | |
return ($result); | |
} | |
private static function strxor_direct($dataA, $dataB) { | |
if (strlen($dataA) != strlen($dataB)) { | |
$e_msg = "Length Not Match"; | |
throw new Exception($e_msg); | |
} | |
return $dataA ^ $dataB; | |
} | |
private static function pkcs7pad($message) { | |
$blocksize = 16; | |
$padsize = $blocksize - (strlen($message) % $blocksize); | |
return $message . str_repeat(chr($padsize), $padsize); | |
} | |
private static function pkcs7unpad($message) { | |
$length = strlen($message); | |
$blocksize = 16; | |
if($length % $blocksize != 0) | |
throw new Exception("Block Size Error"); | |
$padsize = ord($message[$length - 1]); | |
if($padsize === 0) | |
throw new Exception("Zero Padding Found"); | |
$padding = substr($message, -$padsize); | |
if($padsize > $blocksize || substr_count($padding, chr($padsize)) != $padsize) | |
throw new Exception("Padding Corrupted"); | |
return substr($message, 0, $length - $padsize); | |
} | |
} | |
try { | |
$pass = "GOOGLE"; | |
echo $ciphertext = AESCustom::encrypt($pass, "aaaaaaaaaaaaaaaa") . "\n"; | |
echo bin2hex(AESCustom::decrypt($pass, $ciphertext)); | |
} catch (Exception $e) { | |
echo "ERROR: " . $e->getMessage() . " at line " . $e->getLine(); | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment