/app/Services/IdEncryptService.php

https://github.com/luoyangpeng/Ladmin · PHP · 126 lines · 88 code · 13 blank · 25 comment · 10 complexity · 00f70e181e1dcdd147a00d5269f436ea MD5 · raw file

  1. <?php
  2. namespace App\Services;
  3. class IdEncryptService {
  4. /**
  5. * id 加密
  6. * 可用 static::decryption_id() 进行解密
  7. * @param $id
  8. * @return string
  9. */
  10. public static function encryption_id( $id = 0 ){
  11. $id = trim($id);
  12. if(!is_numeric($id)){
  13. return FALSE;
  14. }
  15. $iii = config('id_encrypt.iii');//左侧位数,必需是数字,避免与其它定义重复,故用此定义
  16. $kkk = config('id_encrypt.kkk');//右侧位数,必需是数字
  17. $mmm = config('id_encrypt.mmm');//加的一个常量,必需是数字,这样容纳10亿个数字,加密后的位数依然不变,为16位,与MD5加密一致,会被误认为是md5
  18. $nnn = config('id_encrypt.nnn');//只能填0-9之间的数字,将数字替换为下面的o代表的字符,只替换一次。
  19. $ooo = config('id_encrypt.ooo');//最好是a-f之间的字符,改变上述这五个常量,黑客就无从猜解了.
  20. $ppp = config('id_encrypt.ppp');//只能填0-9之间的数字,将数字替换为下面的o代表的字符,只替换一次。
  21. $qqq = config('id_encrypt.qqq');//最好是a-f之间的字符,改变上述这五个常量,黑客就无从猜解了.
  22. $rrr = config('id_encrypt.rrr');//只能填0-9之间的数字,将数字替换为下面的o代表的字符,只替换一次。
  23. $sss = config('id_encrypt.sss');//最好是a-f之间的字符,改变上述这五个常量,黑客就无从猜解了.
  24. $id_plus=$id1=$id2=$id3=$id_str = '';
  25. $id_plus=$id+$mmm;//加上一个常数进行运算,这是能否解密的关键,同时也可以防止黑客用非数字攻击。
  26. $id1 = substr(md5($id_plus),8,16);
  27. $id2 = substr($id1,0,$iii);//只取前5位
  28. $id3 = substr($id1,-$kkk);//取后2位
  29. $replace_count = 1;
  30. $id_str = substr($id_plus, 0, 1).preg_replace("/{$nnn}/", $ooo, substr($id_plus, 1), $replace_count);//替换第一个出现的数字为字符
  31. $id_str = substr($id_str, 0, 1).preg_replace("/{$ppp}/", $qqq, substr($id_str, 1), $replace_count);//替换第一个出现的数字为字符
  32. $id_str = substr($id_str, 0, 1).preg_replace("/$rrr/", $sss, substr($id_str, 1), $replace_count);//替换第一个出现的数字为字符
  33. return $id2.$id_str.$id3; //encryption_id是呈现给读者的,是加密过的,实际上它还可以进一步进行打乱次序运算
  34. }
  35. /**
  36. * id 解密
  37. * 适用于 static::encryption_id() 加密算法得到的key
  38. * @param $key
  39. * @return int|string
  40. */
  41. public static function decryption_id( $key = 0 ){
  42. $key = trim($key);
  43. if(!ctype_alnum($key) or strlen($key) != 16 ){
  44. return FALSE;
  45. }
  46. $iii = config('id_encrypt.iii');//左侧位数,必需是数字,避免与其它定义重复,故用此定义
  47. $kkk = config('id_encrypt.kkk');//右侧位数,必需是数字
  48. $mmm = config('id_encrypt.mmm');//加的一个常量,必需是数字,这样容纳10亿个数字,加密后的位数依然不变,为16位,与MD5加密一致,会被误认为是md5
  49. $nnn = config('id_encrypt.nnn');//只能填0-9之间的数字,将数字替换为下面的o代表的字符,只替换一次。
  50. $ooo = config('id_encrypt.ooo');//最好是a-f之间的字符,改变上述这五个常量,黑客就无从猜解了.
  51. $ppp = config('id_encrypt.ppp');//只能填0-9之间的数字,将数字替换为下面的o代表的字符,只替换一次。
  52. $qqq = config('id_encrypt.qqq');//最好是a-f之间的字符,改变上述这五个常量,黑客就无从猜解了.
  53. $rrr = config('id_encrypt.rrr');//只能填0-9之间的数字,将数字替换为下面的o代表的字符,只替换一次。
  54. $sss = config('id_encrypt.sss');//最好是a-f之间的字符,改变上述这五个常量,黑客就无从猜解了.
  55. $id1=$id2=$id3=$id_left=$id_right=$id_left_1=$id_right_1=$x=$x1=$id3_md5=$id1_str=$id_plus='';
  56. $id_left_1=substr($key,0,5);//取MD5加密的前5位
  57. $id_right_1=substr($key,-$kkk);//取加密后2位
  58. $x=strlen($key);//计算长度
  59. $x1=$x-$iii-$kkk;//实际ID值的长度
  60. $replace_count =1;
  61. $id_plus =substr($key,$iii,$x1);
  62. $id_plus = substr($id_plus, 0, 1).preg_replace("/{$ooo}/", $nnn, substr($id_plus, 1), $replace_count);//替换第一个出现的数字为字符
  63. $id_plus = substr($id_plus, 0, 1).preg_replace("/{$qqq}/", $ppp, substr($id_plus, 1), $replace_count);//替换第一个出现的数字为字符
  64. $id_plus = substr($id_plus, 0, 1).preg_replace("/{$sss}/", $rrr, substr($id_plus, 1), $replace_count);//替换第一个出现的数字为字符
  65. if(!is_numeric($id_plus)){
  66. $decryption_id=0;
  67. }
  68. $id_plus_md5=substr(md5($id_plus),8,16);
  69. $id_left = substr($id_plus_md5, 0, $iii);
  70. $id_right=substr($id_plus_md5,-$kkk);
  71. if($id_left==$id_left_1 and $id_right==$id_right_1){
  72. $decryption_id=$id_plus-$mmm;
  73. }else{
  74. $decryption_id=0;
  75. }
  76. return $decryption_id;
  77. }
  78. /**
  79. * id 解密 如果解密失败则终止程序继续运行
  80. * @param int $key
  81. * @param string $key_name
  82. * @return int|string|void
  83. */
  84. public static function decryptionOrDie($key = 0, $key_name = 'ID'){
  85. $value = static::decryption_id($key);
  86. if( $value == $key or !$value ){
  87. return false;
  88. }
  89. return $value;
  90. }
  91. /**
  92. * 加密助手
  93. *
  94. * @param array $array 需要加密的数组
  95. * @param array $keys 需要加密的字段
  96. * @return array
  97. */
  98. public static function encryption_helper( &$array, $keys = ['id', 'uid'] ){
  99. $keys = is_string($keys) ? explode(',', $keys) : $keys;
  100. foreach ($array as $key => $value) {
  101. if (is_array($value)) {
  102. static::encryption_helper($array[$key], $keys);
  103. } else {
  104. if (in_array($key, $keys) and is_numeric($value)) {
  105. $array[$key] = static::encryption_id($value);
  106. } else{
  107. $array[$key] = $value;
  108. }
  109. }
  110. }
  111. return $array;
  112. }
  113. }