CryptToolSodium   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 0
Metric Value
wmc 21
lcom 0
cbo 3
dl 0
loc 208
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A makeBox() 0 7 1
A makeSecretBox() 0 4 1
A openBox() 0 6 1
A openSecretBox() 0 4 1
A generateKeyPair() 0 6 1
A createRandom() 0 4 1
A derivePublicKey() 0 4 1
A bin2hex() 0 5 1
A hex2bin() 0 5 1
A stringCompare() 0 10 3
A removeVar() 0 13 3
A isSupported() 0 4 2
A validate() 0 6 2
A getName() 0 3 1
A getDescription() 0 4 1
1
<?php
2
/**
3
 * @author Threema GmbH
4
 * @copyright Copyright (c) 2015-2016 Threema GmbH
5
 */
6
7
8
namespace Threema\MsgApi\Tools;
9
10
use Threema\Core\Exception;
11
use Threema\Core\KeyPair;
12
13
/**
14
 * Contains static methods to do various Threema cryptography related tasks.
15
 * Support libsodium >= 0.2.0 (Namespaces)
16
 *
17
 * @package Threema\Core
18
 */
19
class CryptToolSodium extends CryptTool {
20
	/**
21
	 * @param string $data
22
	 * @param string $nonce
23
	 * @param string $senderPrivateKey
24
	 * @param string $recipientPublicKey
25
	 * @return string encrypted box
26
	 */
27
	protected function makeBox($data, $nonce, $senderPrivateKey, $recipientPublicKey) {
28
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
29
		$kp = \Sodium\crypto_box_keypair_from_secretkey_and_publickey($senderPrivateKey, $recipientPublicKey);
30
31
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
32
		return \Sodium\crypto_box($data, $nonce, $kp);
33
	}
34
35
	/**
36
	 * make a secret box
37
	 *
38
	 * @param $data
39
	 * @param $nonce
40
	 * @param $key
41
	 * @return mixed
42
	 */
43
	protected function makeSecretBox($data, $nonce, $key) {
44
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
45
		return \Sodium\crypto_secretbox($data, $nonce, $key);
46
	}
47
48
49
	/**
50
	 * @param string $box
51
	 * @param string $recipientPrivateKey
52
	 * @param string $senderPublicKey
53
	 * @param string $nonce
54
	 * @return null|string
55
	 */
56
	protected function openBox($box, $recipientPrivateKey, $senderPublicKey, $nonce) {
57
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
58
		$kp = \Sodium\crypto_box_keypair_from_secretkey_and_publickey($recipientPrivateKey, $senderPublicKey);
59
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
60
		return \Sodium\crypto_box_open($box, $nonce, $kp);
61
	}
62
63
	/**
64
	 * decrypt a secret box
65
	 *
66
	 * @param string $box as binary
67
	 * @param string $nonce as binary
68
	 * @param string $key as binary
69
	 * @return string as binary
70
	 */
71
	protected function openSecretBox($box, $nonce, $key) {
72
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
73
		return \Sodium\crypto_secretbox_open($box, $nonce, $key);
74
	}
75
76
	/**
77
	 * Generate a new key pair.
78
	 *
79
	 * @return KeyPair the new key pair
80
	 */
81
	final public function generateKeyPair() {
82
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
83
		$kp = \Sodium\crypto_box_keypair();
84
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
85
		return new KeyPair(\Sodium\crypto_box_secretkey($kp), \Sodium\crypto_box_publickey($kp));
86
	}
87
88
	/**
89
	 * @param int $size
90
	 * @return string
91
	 */
92
	protected function createRandom($size) {
93
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
94
		return \Sodium\randombytes_buf($size);
95
	}
96
97
	/**
98
	 * Derive the public key
99
	 *
100
	 * @param string $privateKey in binary
101
	 * @return string public key as binary
102
	 */
103
	final public function derivePublicKey($privateKey) {
104
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
105
		return \Sodium\crypto_box_publickey_from_secretkey($privateKey);
106
	}
107
108
	/**
109
	 * Converts a binary string to an hexdecimal string.
110
	 *
111
	 * This is the same as PHP's bin2hex() implementation, but it is resistant to
112
	 * timing attacks.
113
	 *
114
	 * @link https://paragonie.com/book/pecl-libsodium/read/03-utilities-helpers.md#bin2hex
115
	 * @param  string $binaryString The binary string to convert
116
	 * @return string
117
	 */
118
	public function bin2hex($binaryString)
119
	{
120
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
121
		return \Sodium\bin2hex($binaryString);
122
	}
123
124
	/**
125
	 * Converts an hexdecimal string to a binary string.
126
	 *
127
	 * This is the same as PHP's hex2bin() implementation, but it is resistant to
128
	 * timing attacks.
129
	 *
130
	 * @link https://paragonie.com/book/pecl-libsodium/read/03-utilities-helpers.md#hex2bin
131
	 * @param  string $hexString The hex string to convert
132
	 * @param  string|null $ignore	(optional) Characters to ignore
133
	 * @throws \Threema\Core\Exception
134
	 * @return string
135
	 */
136
	public function hex2bin($hexString, $ignore = null)
137
	{
138
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
139
		return \Sodium\hex2bin($hexString, $ignore);
140
	}
141
142
143
	/**
144
	 * Compares two strings in a secure way.
145
	 *
146
	 * This is the same as PHP's strcmp() implementation, but it is resistant to
147
	 * timing attacks.
148
	 *
149
	 * @link https://paragonie.com/book/pecl-libsodium/read/03-utilities-helpers.md#compare
150
	 * @param  string $str1 The first string
151
	 * @param  string $str2 The second string
152
	 * @return bool
153
	 */
154
	public function stringCompare($str1, $str2)
155
	{
156
		// check variable type manually
157
		if (!is_string($str1) || !is_string($str2)) {
158
			return false;
159
		}
160
161
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
162
		return \Sodium\memcmp($str1, $str2) === 0;
163
	}
164
165
	/**
166
	 * Unsets/removes a variable.
167
	 *
168
	 * Important: When using PHPv7, make sure to have at least version 1.0.1 of
169
	 * the Libsodium PECL (libsodium-php) installed. Otherwise this falls back to
170
	 * the (insecure) PHP method of removing a variable.
171
	 *
172
	 * @link https://paragonie.com/book/pecl-libsodium/read/03-utilities-helpers.md#memzero
173
	 * @param  string $var A variable, passed by reference
174
	 */
175
	public function removeVar(&$var)
176
	{
177
		// check if version is compatible
178
		if (version_compare(PHP_VERSION, '7.0', '>=') &&
179
			version_compare(phpversion('libsodium'), '1.0.1', '<')
180
		) {
181
			// if not, fall back to PHP implementation
182
			return parent::removeVar($var);
183
		}
184
185
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
186
		return \Sodium\memzero($var);
187
	}
188
189
	/**
190
	 * Check if implementation supported
191
	 * @return bool
192
	 */
193
	public function isSupported() {
194
		return true === extension_loaded('libsodium')
195
			&& false === method_exists('Sodium', 'sodium_version_string');
196
	}
197
198
	/**
199
	 * Validate crypt tool
200
	 *
201
	 * @return bool
202
	 * @throws Exception
203
	 */
204
	public function validate() {
205
		if(false === $this->isSupported()) {
206
			throw new Exception('Sodium implementation not supported');
207
		}
208
		return true;
209
	}
210
211
	/**
212
	 * @return string
213
	 */
214
	public function getName() {
215
		return 'sodium';
216
	}
217
218
	/**
219
	 * Description of the CryptTool
220
	 * @return string
221
	 */
222
	public function getDescription() {
223
		/** @noinspection PhpUndefinedNamespaceInspection @noinspection PhpUndefinedFunctionInspection */
224
		return 'Sodium implementation '.\Sodium\version_string().' with PHP binding '.phpversion('libsodium');
225
	}
226
}
227