Last active
March 13, 2019 11:05
-
-
Save diyism/4f4bf07c2cc814f3318f7e57d501ca5d to your computer and use it in GitHub Desktop.
aes-256-cbc / encrypt integer / shorten integer in php
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 | |
$enc=encrypt_int(3524, 'aaaa1111bbbb3333cccc5555dddd7777'); | |
echo $enc.'<hr>'; | |
$int=decrypt_int($enc, 'aaaa1111bbbb3333cccc5555dddd7777'); | |
echo $int.'<hr>'; | |
//输出: 5e91d2b65b2a<hr>3524<hr> | |
//输出: a08f854f3ddf<hr>3524<hr> | |
//... | |
//实际的$iv_short.$ac_short, $crypt_text 分别是: | |
//5e91d2b6, 5b2a | |
//a08f854f, 3ddf | |
//... | |
//$key需要32个字符 | |
function encrypt_int($int, $key) | |
{ | |
$int=dechex($int); | |
$int=strlen($int)%2===0?hex2bin($int):hex2bin('0'.$int); | |
$hex=bin2hex(MoreUnsafeOpensslAES::encrypt($int, $key, 2, 3)); | |
$rtn=base_convert($hex, 16, 36); | |
return $rtn; | |
} | |
function decrypt_int($enc, $key) | |
{ | |
$hex=base_convert($enc, 36, 16); | |
$hex=strlen($hex)%2===0?hex2bin($hex):hex2bin('0'.$hex); | |
return hexdec(bin2hex(MoreUnsafeOpensslAES::decrypt($hex, $key, 2, 3))); | |
} | |
//参考http://www.coldxiangyu.com/2017/06/27/AES%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95/ | |
//只有cfb, ofb才能保持内容长度不变, 所以把aes-256-cbc降级aes-256-cfb, | |
//但iv还是很长, 只能对iv动手脚(减少iv len并padding), 就变得more unsafe更不安全, | |
//要验证机制(Authentication Code)的话还要加ac len, 至少要占3位才防刷(1600万), 剩下的iv len至少2位才能对单个数据提供6万的变动空间 | |
//用来加密很短的自增id之类还是可以凑合一用的 | |
class MoreUnsafeOpensslAES | |
{ | |
const METHOD = 'aes-256-cfb'; | |
public static function encrypt($message, $key, $iv_len, $ac_len) | |
{ | |
if (mb_strlen($key, '8bit') !== 32) { | |
throw new Exception("Needs a 256-bit key!"); | |
} | |
$ivsize=openssl_cipher_iv_length(self::METHOD); | |
$iv=openssl_random_pseudo_bytes($ivsize); | |
$iv_short=substr($iv, 0, $iv_len); | |
$ac_short=substr(hash_hmac('md5', $message.$iv_short, $key, 1), 0, $ac_len); | |
$iv=str_pad($iv_short.$ac_short, $ivsize, "\0", STR_PAD_RIGHT); | |
$ciphertext = openssl_encrypt( | |
$message, | |
self::METHOD, | |
$key, | |
OPENSSL_RAW_DATA, | |
$iv | |
); | |
return $iv_short.$ac_short.$ciphertext; | |
} | |
public static function decrypt($message, $key, $iv_len, $ac_len) | |
{ | |
if (mb_strlen($key, '8bit') !== 32) { | |
throw new Exception("Needs a 256-bit key!"); | |
} | |
$ivsize = openssl_cipher_iv_length(self::METHOD); | |
$iv_short=mb_substr($message, 0, $iv_len, '8bit'); | |
$ac_short=mb_substr($message, $iv_len, $ac_len, '8bit'); | |
$iv=str_pad($iv_short.$ac_short, $ivsize, "\0", STR_PAD_RIGHT); | |
$ciphertext = mb_substr($message, $iv_len+$ac_len, null, '8bit'); | |
$clear_text=openssl_decrypt( | |
$ciphertext, | |
self::METHOD, | |
$key, | |
OPENSSL_RAW_DATA, | |
$iv | |
); | |
$tmp=substr(hash_hmac('md5', $clear_text.$iv_short, $key, 1), 0, $ac_len); | |
if ($tmp!==$ac_short) | |
{ | |
return ''; | |
} | |
return $clear_text; | |
} | |
} | |
//因为mcrypt的名字MCRYPT_RIJNDAEL_128里128是key length 128而不是block size 256, 容易搞混淆, | |
//以及需要自己写PKCS7 Padding等问题, 因而php里aes-256-cbc推荐的实现是用openssl写: | |
//参考:https://paragonie.com/blog/2015/05/if-you-re-typing-word-mcrypt-into-your-code-you-re-doing-it-wrong | |
class UnsafeOpensslAES | |
{ | |
const METHOD = 'aes-256-cbc'; | |
public static function encrypt($message, $key) | |
{ | |
if (mb_strlen($key, '8bit') !== 32) { | |
throw new Exception("Needs a 256-bit key!"); | |
} | |
$ivsize = openssl_cipher_iv_length(self::METHOD); | |
$iv = openssl_random_pseudo_bytes($ivsize); | |
$ciphertext = openssl_encrypt( | |
$message, | |
self::METHOD, | |
$key, | |
OPENSSL_RAW_DATA, | |
$iv | |
); | |
return $iv . $ciphertext; | |
} | |
public static function decrypt($message, $key) | |
{ | |
if (mb_strlen($key, '8bit') !== 32) { | |
throw new Exception("Needs a 256-bit key!"); | |
} | |
$ivsize = openssl_cipher_iv_length(self::METHOD); | |
$iv = mb_substr($message, 0, $ivsize, '8bit'); | |
$ciphertext = mb_substr($message, $ivsize, null, '8bit'); | |
return openssl_decrypt( | |
$ciphertext, | |
self::METHOD, | |
$key, | |
OPENSSL_RAW_DATA, | |
$iv | |
); | |
} | |
} | |
//整数的话用这两个函数更短小: | |
function shorten_int($id) | |
{ | |
$id=dechex($id); | |
$id=strlen($id)%2===0?hex2bin($id):hex2bin('0'.$id); | |
$id=base64_encode($id); | |
$id=strtr($id, array('/'=>'_', '+'=>'-', '='=>'')); | |
return $id; | |
} | |
function unshorten_int($id) | |
{ | |
$id=strtr($id, array('-'=>'+', '_'=>'/')); | |
$id=base64_decode($id); | |
$id=bin2hex($id); | |
return base_convert($id, 16, 10); | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment