1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
cookiescrypter.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\Web;
4
5use Bitrix\Main\Config;
6use Bitrix\Main\Security\Cipher;
7use Bitrix\Main\Security\SecurityException;
8use Bitrix\Main\Session\KernelSession;
9use Bitrix\Main\SystemException;
10
15final class CookiesCrypter
16{
17 public const COOKIE_MAX_SIZE = 4096;
19
20 private const SIGN_PREFIX = '-crpt-';
21 private const CIPHER_KEY_SUFFIX = 'cookiecrypter';
22
23 protected ?string $cipherKey;
24 protected Cipher $cipher;
25
26 public function __construct()
27 {
28 }
29
35 protected function buildCipher(): self
36 {
37 if (isset($this->cipher))
38 {
39 return $this;
40 }
41
42 $configuration = Config\Configuration::getInstance();
43
44 $this->cipher = new Cipher();
45 $this->cipherKey = $configuration->get('crypto')['crypto_key'] ?? null;
46 if (!$this->cipherKey)
47 {
48 throw new SystemException('There is no crypto[crypto_key] in .settings.php. Generate it.');
49 }
50 $this->cipherKey = $this->prependSuffixToKey($this->cipherKey);
51
52 return $this;
53 }
54
60 protected function prependSuffixToKey(string $key): string
61 {
62 return $key . self::CIPHER_KEY_SUFFIX;
63 }
64
72 public function encrypt(CryptoCookie $cookie): iterable
73 {
74 $result = [];
75 $encryptedValue = $this->encryptValue($cookie->getValue());
76 foreach ($this->packCookie($cookie, $encryptedValue) as $partCookie)
77 {
78 $result[] = $partCookie;
79 }
80
81 return $result;
82 }
83
91 public function decrypt(string $name, string $value, iterable $cookies): string
92 {
93 if (!$this->shouldDecrypt($name, $value))
94 {
95 return $value;
96 }
97
98 try
99 {
100 return $this->unpackCookie($value, $cookies);
101 }
102 catch (SecurityException)
103 {
104 //just skip cookies which we can't decrypt.
105 }
106
107 return '';
108 }
109
116 protected function packCookie(CryptoCookie $cookie, string $encryptedValue): iterable
117 {
118 $length = \strlen($encryptedValue);
119 $maxContentLength = self::COOKIE_MAX_SIZE - self::COOKIE_RESERVED_SUFFIX_BYTES - \strlen($cookie->getName());
120
121 $i = 0;
122 $parts = ($length / $maxContentLength);
123 $pack = [];
124 do
125 {
126 $startPosition = $i * $maxContentLength;
127 $partCookie = new Cookie("{$cookie->getName()}_{$i}", substr($encryptedValue, $startPosition, $maxContentLength));
128 $cookie->copyAttributesTo($partCookie);
129 $pack["{$cookie->getOriginalName()}_{$i}"] = $partCookie;
130
131 $i++;
132 }
133 while($parts > $i);
134
135 $mainCookie = new Cookie($cookie->getName(), $this->prependSign(implode(',', array_keys($pack))));
136 $cookie->copyAttributesTo($mainCookie);
137
138 array_unshift($pack, $mainCookie);
139
140 return $pack;
141 }
142
149 protected function unpackCookie(string $mainCookie, iterable $cookies): string
150 {
151 $mainCookie = $this->removeSign($mainCookie);
152 $packedNames = array_flip(array_filter(explode(',', $mainCookie)));
153 $parts = [];
154
155 foreach ($cookies as $name => $value)
156 {
157 if (!isset($packedNames[$name]))
158 {
159 continue;
160 }
161
162 $parts[$packedNames[$name]] = $value;
163 if (\count($parts) === \count($packedNames))
164 {
165 break;
166 }
167 }
168 ksort($parts);
169 $encryptedValue = implode('', $parts);
170
171 return $this->decryptValue($encryptedValue);
172 }
173
182 protected function encryptValue(string $value): string
183 {
184 $this->buildCipher();
185 if (\function_exists('gzencode'))
186 {
187 $value = gzencode($value);
188 }
189
190 return $this->encodeUrlSafeB64($this->cipher->encrypt($value, $this->getCipherKey()));
191 }
192
200 protected function decryptValue(string $value): string
201 {
202 $this->buildCipher();
203
204 $value = $this->cipher->decrypt($this->decodeUrlSafeB64($value), $this->getCipherKey());
205 if (\function_exists('gzdecode'))
206 {
207 $value = gzdecode($value);
208 }
209
210 return $value;
211 }
212
218 private function decodeUrlSafeB64(string $input): string
219 {
220 $padLength = 4 - \strlen($input) % 4;
221 $input .= str_repeat('=', $padLength);
222
223 return base64_decode(strtr($input, '-_', '+/')) ?: '';
224 }
225
231 private function encodeUrlSafeB64(string $input): string
232 {
233 return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
234 }
235
241 public function shouldEncrypt(Cookie $cookie): bool
242 {
243 return $cookie instanceof CryptoCookie;
244 }
245
252 public function shouldDecrypt(string $cookieName, string $cookieValue): bool
253 {
254 if ($cookieName === KernelSession::COOKIE_NAME)
255 {
256 return true;
257 }
258
259 return str_starts_with($cookieValue, self::SIGN_PREFIX);
260 }
261
267 protected function prependSign(string $value): string
268 {
269 return self::SIGN_PREFIX . $value;
270 }
271
277 protected function removeSign(string $value): string
278 {
279 return substr($value, \strlen(self::SIGN_PREFIX));
280 }
281
286 public function getCipherKey(): string
287 {
288 return $this->cipherKey;
289 }
290}
static getInstance($moduleId=null)
Определения configuration.php:45
prependSign(string $value)
Определения cookiescrypter.php:267
packCookie(CryptoCookie $cookie, string $encryptedValue)
Определения cookiescrypter.php:116
prependSuffixToKey(string $key)
Определения cookiescrypter.php:60
const COOKIE_RESERVED_SUFFIX_BYTES
Определения cookiescrypter.php:18
shouldDecrypt(string $cookieName, string $cookieValue)
Определения cookiescrypter.php:252
encrypt(CryptoCookie $cookie)
Определения cookiescrypter.php:72
decryptValue(string $value)
Определения cookiescrypter.php:200
removeSign(string $value)
Определения cookiescrypter.php:277
decrypt(string $name, string $value, iterable $cookies)
Определения cookiescrypter.php:91
shouldEncrypt(Cookie $cookie)
Определения cookiescrypter.php:241
encryptValue(string $value)
Определения cookiescrypter.php:182
unpackCookie(string $mainCookie, iterable $cookies)
Определения cookiescrypter.php:149
$result
Определения get_property_values.php:14
$name
Определения menu_edit.php:35
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936