· 4 years ago · Jun 29, 2021, 07:56 PM
1class Encrypt
2{
3 /**
4 * This defines the accepted method of transforming array and objects into strings
5 * switch to serialize if you don't want to use a json method
6 *
7 * @var string
8 */
9 private static $string_mode = 'json';
10
11 /**
12 * Base64 characters
13 *
14 * @var string
15 */
16 private static $from = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/';
17
18 /**
19 * Base64 replacement characters, used only if config()->encrypt_replacement does not exist
20 *
21 * @var string
22 */
23 private static $to = 'pHt1r5j0sCe34NDzqQOV8kBKG9XmwvfiAIdLZ2aRlxSYcuPWnybUgETJ6MhFo7.-';
24
25 /**
26 * Encryption secret key, used only if config()->encrypt_key does not exist
27 *
28 * @var string
29 */
30 private static $encrypt_key = 'より古いバージョンから対応しているようなので を使う 未知の形式';
31
32 /**
33 * Encrypt a string following a salt, salt should not be passed if it is not a hash
34 *
35 * @param string $password
36 * @param string $salt
37 * @return string
38 */
39 public static function hash($password, $salt = ''){
40 $salt = !$salt ? substr(md5(uniqid(mt_rand(), true)), 0, 31%strlen($password)) : (($r = strlen($salt)%40) && $r%2 ? substr($salt, 0, $r) : substr($salt, -$r));
41 return ($r = strlen($salt)%2 ? $salt:'').sha1($password.$salt).($r ? '':$salt);
42 }
43
44 /**
45 * Compare an unencrypted password with an encrypted password
46 *
47 * @param string $unencrypted
48 * @param string $encrypted
49 * @return string
50 */
51 public static function hash_equals($unencrypted, $encrypted){
52 return hash_equals($encrypted, self::hash($unencrypted, $encrypted));
53 }
54
55 /**
56 * Encrypt and decrypt a string with a secret key
57 *
58 * @param string $str
59 * @param boolean $type
60 * @param string $secret_key
61 * @return string
62 */
63 public static function en($str = '', $type = true, $secret_key = ''){
64 if(!$str || !$secret_key) return '';
65 if (!is_string($str)) $str = (string) $str;
66 $return = '';
67 if(!$type) $str = base64_decode(strtr($str, isset(config()->encrypt_replacement) ? config()->encrypt_replacement : self::$to, self::$from));
68 $a = strlen($str)-1;
69 $b = strlen($secret_key);
70 do{
71 $return .= ($str[$a] ^ $secret_key[$a%$b]);
72 }while ($a--);
73 $return = strrev($return);
74 return $type ? rtrim(strtr(base64_encode($return), self::$from, isset(config()->encrypt_replacement) ? config()->encrypt_replacement : self::$to), '=') : $return;
75 }
76
77 /**
78 * Encrypt an md5 in bytes of a string
79 *
80 * @param string $str
81 * @return string
82 */
83 private static function md5($str){
84 return self::en(md5($str, true), true, isset(config()->encrypt_key) ? config()->encrypt_key : self::$encrypt_key);
85 }
86
87 /**
88 * Convert array and objects to strings
89 *
90 * @param array|object $item
91 * @return string
92 */
93 public static function toText($item){
94 $mode = isset(config()->encrypt_string_mode) ? config()->encrypt_string_mode : self::$string_mode;
95 return $mode == 'query' ? http_build_query($item) : ($mode == 'json' ? json_encode($item) : serialize($item));
96 }
97
98 /**
99 * Encrypt a anyting with secret key
100 *
101 * @param mixed $str
102 * @param string $key
103 * @return string
104 */
105 public static function encode($str, $key = ''){
106 return self::en(is_array($str) || is_object($str) ? self::toText(is_array($str) ? array_random($str) : $str) : $str, true, $key ? $key : (isset(config()->encrypt_key) ? config()->encrypt_key : self::$encrypt_key));
107 }
108
109 /**
110 * Decrypt a anyting with secret key
111 *
112 * @param mixed $str
113 * @param string $key
114 * @return mixed
115 */
116 public static function decode($str, $key = '', $assoc = false){
117 if ($return = self::en($str, false, $key ? $key : (isset(config()->encrypt_key) ? config()->encrypt_key : self::$encrypt_key))){
118 if(is_json($return)){
119 $return = json_decode($return, $assoc);
120 }elseif(is_serialized($return)){
121 $return = unserialize($return);
122 if (!$assoc) $return = (object) $return;
123 }elseif(is_http_query($return)){
124 parse_str($return, $array);
125 $return = !$assoc ? (object) $array : $array;
126 }
127 }
128 return $return;
129 }
130
131 /**
132 * Modified implementation of a JWT
133 *
134 * @param array $header
135 * @param array $payload
136 * @return string
137 */
138 public static function jwt($header, $payload){
139 if (!isset($header['k'])) $header['k'] = self::md5(uniqid(mt_rand(), true));
140 $payload = self::encode($payload, $header['k']);
141 $header = self::encode($header);
142 return $header.'_'.$payload.'_'.self::md5($header.$payload);
143 }
144
145 /**
146 * Check if JWT is valid and returns payload
147 *
148 * @param string $jwt
149 * @return mixed
150 */
151 public static function is_jwt($jwt, $assoc = false){
152 if (!$jwt || !is_string($jwt)) return false;
153 $jwt = explode('_',$jwt);
154 if (count($jwt) !=3 || $jwt[2] != self::md5($jwt[0].$jwt[1])) return false;
155 if ($header = self::decode($jwt[0]) and is_object($header) and $payload = self::decode($jwt[1], $header->k, $assoc) and $payload){
156 if (isset($header->exp) && time() > $header->exp) return false;
157 if (isset($header->iss) && $_SERVER['HTTP_HOST'] != $header->iss) return false;
158 if (isset($header->bwr) && browser().substr(browser_version(), 0, 2) != $header->bwr) return false;
159 if (isset($header->ip) && ip() != $header->ip) return false;
160 return $payload;
161 }
162 return false;
163 }
164
165 /**
166 * Help function to create a JWT
167 *
168 * @param array $data
169 * @param integer $exp
170 * @return string
171 */
172 public static function sign($data, $exp = 1800){
173 return self::jwt([
174 'exp' => time() > $exp ? time() + $exp : $exp,
175 'iss' => $_SERVER['HTTP_HOST'],
176 'bwr' => browser().substr(browser_version(), 0, 2),
177 'ip' => ip()
178 ], $data);
179 }
180}
181