Test Failed
Push — master ( 8c47c2...3acf9f )
by Steve
12:37
created

engine/classes/Elgg/Database/SiteSecret.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Elgg\Database;
3
4
use Elgg\Config as ElggConfig;
5
6
/**
7
 * Manages a site-specific secret key, encoded as a 32 byte string "secret"
8
 *
9
 * The key can have two formats:
10
 *   - Since 1.8.17 all keys generated are Base64URL-encoded with the 1st character set to "z" so that
11
 *     the format can be recognized. With one character lost, this makes the keys effectively 186 bits.
12
 *   - Before 1.8.17 keys were hex-encoded (128 bits) but created from insufficiently random sources.
13
 *
14
 * The hex keys were created with rand() as the only decent source of entropy (the site's creation time
15
 * is not too difficult to find). As such, systems with a low getrandmax() value created particularly
16
 * weak keys. You can check key string using getStrength().
17
 *
18
 * @access private
19
 *
20
 * @package    Elgg.Core
21
 * @subpackage Database
22
 * @since      1.10.0
23
 */
24
class SiteSecret {
25
26
	const CONFIG_KEY = '__site_secret__';
27
28
	/**
29
	 * @var ElggConfig
30
	 */
31
	private $config;
32
33
	/**
34
	 * Constructor
35
	 *
36
	 * @param ElggConfig $config Config service
37
	 */
38 196
	public function __construct(ElggConfig $config) {
39 196
		$this->config = $config;
40 196
	}
41
42
	/**
43
	 * @var string
44
	 */
45
	private $test_secret = '';
46
47
	/**
48
	 * Set a secret to be used in testing
49
	 *
50
	 * @param string $secret Testing site secret. 32 alphanums starting with "z"
51
	 * @return void
52
	 */
53 196
	public function setTestingSecret($secret) {
54 196
		$this->test_secret = $secret;
55 196
	}
56
57
	/**
58
	 * Initialise the site secret (32 bytes: "z" to indicate format + 186-bit key in Base64 URL).
59
	 *
60
	 * Used during installation and saves as a config.
61
	 *
62
	 * Note: Old secrets were hex encoded.
63
	 *
64
	 * @return mixed The site secret hash or false
65
	 * @access private
66
	 */
67
	function init() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
68
		$secret = 'z' . _elgg_services()->crypto->getRandomString(31);
69
70
		if ($this->config->save(self::CONFIG_KEY, $secret)) {
71
			return $secret;
72
		}
73
74
		return false;
75
	}
76
77
	/**
78
	 * Returns the site secret.
79
	 *
80
	 * Used to generate difficult to guess hashes for sessions and action tokens.
81
	 *
82
	 * @param bool $raw If true, a binary key will be returned
83
	 *
84
	 * @return string Site secret.
85
	 * @access private
86
	 */
87 54
	function get($raw = false) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
88 54
		if ($this->test_secret) {
89 54
			$secret = $this->test_secret;
90
		} else {
91
			$secret = $this->config->get(self::CONFIG_KEY);
92
		}
93 54
		if (!$secret) {
94
			$secret = $this->init();
95
		}
96
97 54
		if ($raw) {
98
			// try to return binary key
99 54
			if ($secret[0] === 'z') {
100
				// new keys are "z" + base64URL
101 54
				$base64 = strtr(substr($secret, 1), '-_', '+/');
102 54
				$key = base64_decode($base64);
103 54
				if ($key !== false) {
104
					// on failure, at least return string key :/
105 54
					return $key;
106
				}
107
			} else {
108
				// old keys are hex
109
				return hex2bin($secret);
110
			}
111
		}
112
113
		return $secret;
114
	}
115
116
	/**
117
	 * Get the strength of the site secret
118
	 *
119
	 * If "weak" or "moderate" is returned, this assumes we're running on the same system that created
120
	 * the key.
121
	 *
122
	 * @return string "strong", "moderate", or "weak"
123
	 * @access private
124
	 */
125
	function getStrength() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
126
		$secret = $this->get();
127
		if ($secret[0] !== 'z') {
128
			$rand_max = getrandmax();
129
			if ($rand_max < pow(2, 16)) {
130
				return 'weak';
131
			}
132
			if ($rand_max < pow(2, 32)) {
133
				return 'moderate';
134
			}
135
		}
136
		return 'strong';
137
	}
138
}
139