SiteSecret::init()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 9
ccs 0
cts 5
cp 0
crap 6
rs 9.9666
c 0
b 0
f 0
1
<?php
2
namespace Elgg\Database;
3
4
/**
5
 * Manages a site-specific secret key, encoded as a 32 byte string "secret"
6
 *
7
 * The key can have two formats:
8
 *   - Since 1.8.17 all keys generated are Base64URL-encoded with the 1st character set to "z" so that
9
 *     the format can be recognized. With one character lost, this makes the keys effectively 186 bits.
10
 *   - Before 1.8.17 keys were hex-encoded (128 bits) but created from insufficiently random sources.
11
 *
12
 * The hex keys were created with rand() as the only decent source of entropy (the site's creation time
13
 * is not too difficult to find). As such, systems with a low getrandmax() value created particularly
14
 * weak keys. You can check key string using getStrength().
15
 *
16
 * @access private
17
 *
18
 * @package    Elgg.Core
19
 * @subpackage Database
20
 * @since      1.10.0
21
 */
22
class SiteSecret {
23
24
	/**
25
	 * Initialise the site secret (32 bytes: "z" to indicate format + 186-bit key in Base64 URL).
26
	 *
27
	 * Used during installation and saves as a datalist.
28
	 *
29
	 * Note: Old secrets were hex encoded.
30
	 *
31
	 * @return mixed The site secret hash or false
32
	 * @access private
33
	 */
34
	function init() {
35
		$secret = 'z' . _elgg_services()->crypto->getRandomString(31);
36
37
		if (_elgg_services()->datalist->set('__site_secret__', $secret)) {
38
			return $secret;
39
		}
40
41
		return false;
42
	}
43
44
	/**
45
	 * Returns the site secret.
46
	 *
47
	 * Used to generate difficult to guess hashes for sessions and action tokens.
48
	 *
49
	 * @param bool $raw If true, a binary key will be returned
50
	 *
51
	 * @return string Site secret.
52
	 * @access private
53
	 */
54
	function get($raw = false) {
55
		$secret = _elgg_services()->datalist->get('__site_secret__');
56
		if (!$secret) {
57
			$secret = init_site_secret();
58
		}
59
60
		if ($raw) {
61
			// try to return binary key
62
			if ($secret[0] === 'z') {
63
				// new keys are "z" + base64URL
64
				$base64 = strtr(substr($secret, 1), '-_', '+/');
65
				$key = base64_decode($base64);
66
				if ($key !== false) {
67
					// on failure, at least return string key :/
68
					return $key;
69
				}
70
			} else {
71
				// old keys are hex
72
				return hex2bin($secret);
73
			}
74
		}
75
76
		return $secret;
77
	}
78
79
	/**
80
	 * Get the strength of the site secret
81
	 *
82
	 * If "weak" or "moderate" is returned, this assumes we're running on the same system that created
83
	 * the key.
84
	 *
85
	 * @return string "strong", "moderate", or "weak"
86
	 * @access private
87
	 */
88
	function getStrength() {
89
		$secret = get_site_secret();
90
		if ($secret[0] !== 'z') {
91
			$rand_max = getrandmax();
92
			if ($rand_max < pow(2, 16)) {
93
				return 'weak';
94
			}
95
			if ($rand_max < pow(2, 32)) {
96
				return 'moderate';
97
			}
98
		}
99
		return 'strong';
100
	}
101
102
}
103