CryptToolSalt   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 4

Importance

Changes 0
Metric Value
wmc 18
lcom 0
cbo 4
dl 0
loc 161
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A makeBox() 0 4 1
A makeSecretBox() 0 4 1
A openBox() 0 14 3
A openSecretBox() 0 9 2
A generateKeyPair() 0 4 1
A createRandom() 0 3 1
A derivePublicKey() 0 4 1
A encryptImageData() 0 19 2
A isSupported() 0 3 1
A validate() 0 10 3
A getName() 0 3 1
A getDescription() 0 3 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 Salt;
11
use SaltException;
12
use Threema\Core\Exception;
13
use Threema\Core\KeyPair;
14
15
/**
16
 * Contains static methods to do various Threema cryptography related tasks.
17
 *
18
 * @package Threema\Core
19
 */
20
class CryptToolSalt extends CryptTool {
21
	/**
22
	 * @param string $data
23
	 * @param string $nonce
24
	 * @param string $senderPrivateKey
25
	 * @param string $recipientPublicKey
26
	 * @return string encrypted box
27
	 */
28
	protected function makeBox($data, $nonce, $senderPrivateKey, $recipientPublicKey) {
29
		return Salt::box($data, $senderPrivateKey, $recipientPublicKey, $nonce)
30
			->slice(16)->toString();
31
	}
32
33
	/**
34
	 * @param string $data
35
	 * @param string $nonce
36
	 * @param string  $key
37
	 * @return string encrypted secret box
38
	 */
39
	protected function makeSecretBox($data, $nonce, $key) {
40
		return Salt::secretbox($data, $nonce, $key)
41
			->slice(16)->toString();
42
	}
43
44
	/**
45
	 * @param string $box
46
	 * @param string $recipientPrivateKey
47
	 * @param string $senderPublicKey
48
	 * @param string $nonce
49
	 * @return null|string
50
	 */
51
	protected function openBox($box, $recipientPrivateKey, $senderPublicKey, $nonce) {
52
		$boxPad = str_repeat("\x00", 16) . $box;
53
		try {
54
			$data = Salt::box_open($boxPad, $recipientPrivateKey, $senderPublicKey, $nonce);
55
		} catch (\SaltException $e) {
0 ignored issues
show
Bug introduced by
The class SaltException does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
56
			$data = null;
57
		}
58
59
		if ($data) {
60
			return substr($data->toString(), 32);
61
		}
62
63
		return null;
64
	}
65
66
	/**
67
	 * decrypt a secret box
68
	 *
69
	 * @param string $box as binary
70
	 * @param string $nonce as binary
71
	 * @param string $key as binary
72
	 * @return string as binary
73
	 */
74
	protected function openSecretBox($box, $nonce, $key) {
75
		$boxPad = str_repeat("\x00", 16) . $box;
76
		$data = Salt::secretbox_open($boxPad, $nonce, $key);
77
78
		if ($data) {
79
			return substr($data->toString(), 32);
80
		}
81
		return null;
82
	}
83
84
85
	/**
86
	 * Generate a new key pair.
87
	 *
88
	 * @return KeyPair the new key pair
89
	 */
90
	final public function generateKeyPair() {
91
		list($privateKeyObject, $publicKeyObject) = Salt::box_keypair();
92
		return new KeyPair($privateKeyObject->toString(), $publicKeyObject->toString());
93
	}
94
95
	/**
96
	 * @param int $size
97
	 * @return string
98
	 */
99
	protected function createRandom($size) {
100
		return Salt::randombytes($size);
101
	}
102
103
	/**
104
	 * Derive the public key
105
	 *
106
	 * @param string $privateKey in binary
107
	 * @return string public key as binary
108
	 */
109
	final public function derivePublicKey($privateKey) {
110
		$privateKeyElement = \FieldElement::fromString($privateKey);
111
		return Salt::instance()->crypto_scalarmult_base($privateKeyElement)->toString();
112
	}
113
114
	/**
115
	 * @param $imageData
116
	 * @param $recipientPublicKey
117
	 * @param $senderPrivateKey
118
	 * @throws \Threema\Core\Exception
119
	 * @return EncryptResult
120
	 */
121
	public function encryptImageData($imageData, $recipientPublicKey, $senderPrivateKey) {
122
		$message = Salt::decodeInput($imageData);
123
		$nonce = $this->randomNonce();
124
		$salt = Salt::instance();
125
126
		//secret key
127
		$key = $salt->scalarmult($senderPrivateKey, $recipientPublicKey);
128
		$data = $salt->encrypt(
129
			$message,
130
			$message->getSize(),
131
			Salt::decodeInput($nonce),
132
			$key);
133
134
		if($data === false) {
135
			throw new Exception('encryption failed');
136
		}
137
138
		return new EncryptResult($data->toString(), $senderPrivateKey, $nonce, strlen($data->toString()));
139
	}
140
141
	/**
142
	 * Check if implementation supported
143
	 * @return bool
144
	 */
145
	public function isSupported() {
146
		return class_exists('Salt');
147
	}
148
149
	/**
150
	 * Validate crypt tool
151
	 *
152
	 * @return bool
153
	 * @throws Exception
154
	 */
155
	public function validate() {
156
		if(false === $this->isSupported()) {
157
			throw new Exception('SALT implementation not supported');
158
		}
159
160
		if(PHP_INT_SIZE < 8) {
161
			throw new Exception('Pure PHP Crypto implementation requires 64Bit PHP. Please install the libsodium PHP extension.');
162
		}
163
		return true;
164
	}
165
166
	/**
167
	 * @return string
168
	 */
169
	public function getName() {
170
		return 'Salt';
171
	}
172
173
	/**
174
	 * Description of the CryptTool
175
	 * @return string
176
	 */
177
	public function getDescription() {
178
		return 'Pure PHP implementation, please try to install and use the libsodium PHP extension for a better performance';
179
	}
180
}
181