1<?php declare(strict_types = 1);
2/*
3** Zabbix
4** Copyright (C) 2001-2021 Zabbix SIA
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19**/
20
21
22/**
23 * Helper class for sign / encrypt data.
24 */
25class CEncryptHelper {
26
27	/**
28	 * Signature algorithm.
29	 */
30	public const SIGN_ALGO = 'sha256';
31
32	/**
33	 * Session secret key.
34	 *
35	 * @var string
36	 */
37	private static $key;
38
39	/**
40	 * Return session key.
41	 *
42	 * @return string|null
43	 */
44	private static function getKey(): ?string {
45		if (!self::$key) {
46			// This if contain copy in CEncryptedCookieSession class.
47			if (CSettingsHelper::getGlobal(CSettingsHelper::SESSION_KEY) === '') {
48				self::$key = self::generateKey();
49
50				if (!self::updateKey(self::$key)) {
51					return null;
52				}
53
54				return self::$key;
55			}
56
57			self::$key = CSettingsHelper::getGlobal(CSettingsHelper::SESSION_KEY);
58		}
59
60		return self::$key;
61	}
62
63	/**
64	 * Timing attack safe string comparison.
65	 *
66	 * @param string $known_string
67	 * @param string $user_string
68	 *
69	 * @return boolean
70	 */
71	public static function checkSign(string $known_string, string $user_string): bool {
72		return hash_equals($known_string, $user_string);
73	}
74
75	/**
76	 * Encrypt string with session key.
77	 *
78	 * @param string $data
79	 *
80	 * @return string
81	 */
82	public static function sign(string $data): string {
83		$key = self::getKey();
84
85		return hash_hmac(self::SIGN_ALGO, $data, $key, false);
86	}
87
88	/**
89	 * Generate random 16 bytes key.
90	 *
91	 * @return string
92	 */
93	public static function generateKey(): string {
94		return bin2hex(openssl_random_pseudo_bytes(16));
95	}
96
97	/**
98	 * Update secret session key.
99	 *
100	 * @param string $key
101	 *
102	 * @return boolean
103	 */
104	public static function updateKey(string $key): bool {
105		$db_config = DB::select('config', ['output' => ['configid']])[0];
106
107		return DBexecute(
108			'UPDATE config'.
109			' SET session_key='.zbx_dbstr($key).
110			' WHERE '.dbConditionInt('configid', [$db_config['configid']])
111		);
112	}
113}
114