Skip to content

Commit c2cc9c7

Browse files
committed
removing sodium from quick encrypt, lower encryption level on arm
1 parent 2711d70 commit c2cc9c7

File tree

3 files changed

+85
-44
lines changed

3 files changed

+85
-44
lines changed

lib/Command/SetupImport.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
use OC\Core\Command\Base;
3838
use OCA\Backup\Db\RemoteRequest;
3939
use OCA\Backup\Exceptions\EncryptException;
40+
use OCA\Backup\Exceptions\PackDecryptException;
4041
use OCA\Backup\Exceptions\RemoteInstanceUidException;
4142
use OCA\Backup\Model\RemoteInstance;
4243
use OCA\Backup\Service\ConfigService;
@@ -115,7 +116,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
115116
if ($key !== '') {
116117
try {
117118
$json = $this->encryptService->decryptString(base64_decode($json), $key);
118-
} catch (EncryptException $e) {
119+
} catch (PackDecryptException $e) {
119120
throw new EncryptException('Invalid Key');
120121
}
121122
}

lib/Service/EncryptService.php

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
use ArtificialOwl\MySmallPhpTools\Traits\TArrayTools;
3535
use Exception;
36-
use OCA\Backup\Exceptions\EncryptException;
3736
use OCA\Backup\Exceptions\EncryptionKeyException;
3837
use OCA\Backup\Exceptions\PackDecryptException;
3938
use OCA\Backup\Exceptions\PackEncryptException;
@@ -60,8 +59,11 @@ class EncryptService {
6059

6160
public const CHACHA = 'chacha';
6261

62+
public const STRING = 'string';
63+
public const STRING_NONCE = 'string-nonce';
6364

64-
public static $LIST = [
65+
66+
public static $EXPORT = [
6567
self::AES_GCM,
6668
self::AES_GCM_NONCE,
6769
self::AES_CBC,
@@ -83,22 +85,29 @@ public function __construct(ConfigService $configService) {
8385

8486

8587
/**
86-
* @param string $data
88+
* @param string $plain
8789
* @param string $key
8890
*
8991
* @return string
90-
* @throws SodiumException
92+
* @throws EncryptionKeyException
93+
* @throws PackEncryptException
9194
*/
92-
public function encryptString(string $data, string $key): string {
93-
try {
94-
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
95-
} catch (Exception $e) {
96-
throw new SodiumException('random_bytes - ' . $e->getMessage());
95+
public function encryptString(string $plain, string &$key = ''): string {
96+
$key = $this->getEncryptionKey(self::STRING, false);
97+
$nonce = $this->getEncryptionKey(self::STRING_NONCE, false);
98+
$encrypted = openssl_encrypt(
99+
$plain,
100+
self::AES_CBC,
101+
$key,
102+
OPENSSL_RAW_DATA,
103+
$nonce
104+
);
105+
106+
if (!$encrypted) {
107+
throw new PackEncryptException('data were not encrypted');
97108
}
98109

99-
$encrypted = $nonce . sodium_crypto_secretbox($data, $nonce, $key);
100-
sodium_memzero($data);
101-
sodium_memzero($key);
110+
$key = base64_encode($key) . '.' . base64_encode($nonce);
102111

103112
return base64_encode($encrypted);
104113
}
@@ -109,37 +118,25 @@ public function encryptString(string $data, string $key): string {
109118
* @param string $key
110119
*
111120
* @return string
112-
* @throws EncryptException
113-
* @throws SodiumException
121+
* @throws PackDecryptException
114122
*/
115123
public function decryptString(string $encrypted, string $key): string {
116-
$key = base64_decode($key);
117-
118-
if ($encrypted === false) {
119-
throw new EncryptException('invalid data');
120-
}
121-
122-
if (mb_strlen($encrypted, '8bit') < (SODIUM_CRYPTO_SECRETBOX_NONCEBYTES
123-
+ SODIUM_CRYPTO_SECRETBOX_MACBYTES)) {
124-
throw new EncryptException('invalid data');
125-
}
126-
127-
$nonce = mb_substr($encrypted, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
128-
$ciphertext = mb_substr($encrypted, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
124+
[$k, $n] = explode('.', $key, 2);
125+
$key = base64_decode($k);
126+
$nonce = base64_decode($n);
129127

130-
$plain = sodium_crypto_secretbox_open(
131-
$ciphertext,
132-
$nonce,
133-
$key
128+
$plain = openssl_decrypt(
129+
$encrypted,
130+
self::AES_CBC,
131+
$key,
132+
OPENSSL_RAW_DATA,
133+
$nonce
134134
);
135135

136136
if ($plain === false) {
137-
throw new EncryptException('invalid data');
137+
throw new PackDecryptException('cannot decrypt data');
138138
}
139139

140-
sodium_memzero($ciphertext);
141-
sodium_memzero($key);
142-
143140
return $plain;
144141
}
145142

@@ -277,7 +274,7 @@ public function decryptFile(string $input, string $output, string $name, string
277274
$this->decryptFileGCM($input, $output, $name);
278275
break;
279276
case self::AES_CBC:
280-
$this->decryptFileOpenSSL($input, $output);
277+
$this->decryptFileCBC($input, $output);
281278
break;
282279
}
283280
}
@@ -323,7 +320,7 @@ public function decryptFileGCM(string $input, string $output, string $name): voi
323320
* @throws PackDecryptException
324321
* @throws SodiumException
325322
*/
326-
public function decryptFileOpenSSL(string $input, string $output): void {
323+
public function decryptFileCBC(string $input, string $output): void {
327324
$key = base64_decode($this->getEncryptionKey(self::AES_CBC));
328325
$nonce = base64_decode($this->getEncryptionKey(self::AES_CBC_IV));
329326
$write = fopen($output, 'wb');
@@ -382,7 +379,7 @@ public function decryptFileChacha(string $input, string $output): void {
382379
*/
383380
public function getEncryptionKeys(bool $generate = false): array {
384381
if ($generate) {
385-
foreach (self::$LIST as $item) {
382+
foreach (self::$EXPORT as $item) {
386383
try {
387384
$this->getEncryptionKey($item);
388385
} catch (EncryptionKeyException $e) {
@@ -402,7 +399,7 @@ public function getEncryptionKeys(bool $generate = false): array {
402399
/**
403400
* @throws EncryptionKeyException
404401
*/
405-
public function getEncryptionKey(string $type): string {
402+
public function getEncryptionKey(string $type, bool $storeIt = true): string {
406403
$keys = $this->getEncryptionKeys();
407404

408405
$key = $this->get($type, $keys);
@@ -413,8 +410,10 @@ public function getEncryptionKey(string $type): string {
413410
throw new EncryptionKeyException($e->getMessage());
414411
}
415412

416-
$keys[$type] = $key;
417-
$this->configService->setAppValue(ConfigService::ENCRYPTION_KEYS, json_encode($keys));
413+
if ($storeIt) {
414+
$keys[$type] = $key;
415+
$this->configService->setAppValue(ConfigService::ENCRYPTION_KEYS, json_encode($keys));
416+
}
418417
}
419418

420419
return $key;
@@ -428,6 +427,10 @@ public function getEncryptionKey(string $type): string {
428427
* @throws Exception
429428
*/
430429
private function generateKey(string $type): string {
430+
if (!$this->isSodiumAvailable()) {
431+
return $this->generateKeyNative($type);
432+
}
433+
431434
switch ($type) {
432435
case self::CHACHA:
433436
return base64_encode(random_bytes(SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES));
@@ -437,6 +440,34 @@ private function generateKey(string $type): string {
437440
case self::AES_CBC_IV:
438441
case self::AES_GCM_NONCE:
439442
return base64_encode(random_bytes(SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES));
443+
case self::STRING:
444+
return base64_encode(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES));
445+
case self::STRING_NONCE:
446+
return base64_encode(random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES));
447+
}
448+
449+
throw new EncryptionKeyException('unknown key type');
450+
}
451+
452+
453+
/**
454+
* @param string $type
455+
*
456+
* @return string
457+
* @throws EncryptionKeyException
458+
*/
459+
private function generateKeyNative(string $type): string {
460+
switch ($type) {
461+
case self::CHACHA:
462+
case self::AES_GCM:
463+
case self::AES_CBC:
464+
case self::STRING:
465+
return base64_encode(random_bytes(32));
466+
case self::AES_CBC_IV:
467+
case self::AES_GCM_NONCE:
468+
return base64_encode(random_bytes(12));
469+
case self::STRING_NONCE:
470+
return base64_encode(random_bytes(24));
440471
}
441472

442473
throw new EncryptionKeyException('unknown key type');
@@ -451,6 +482,17 @@ private function useSodiumCryptoAead(): bool {
451482
return false;
452483
}
453484

485+
if (!$this->isSodiumAvailable()) {
486+
return false;
487+
}
488+
454489
return sodium_crypto_aead_aes256gcm_is_available();
455490
}
491+
492+
/**
493+
* @return bool
494+
*/
495+
private function isSodiumAvailable(): bool {
496+
return extension_loaded('sodium');
497+
}
456498
}

lib/Service/ExportService.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,7 @@ public function export(bool $encrypted, string &$key = ''): string {
9595

9696
$data = json_encode($setup);
9797
if ($encrypted) {
98-
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
9998
$data = $this->encryptService->encryptString($data, $key);
100-
$key = base64_encode($key);
10199
}
102100

103101
return $data;

0 commit comments

Comments
 (0)