%PDF- %PDF-
| Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Services/ |
| Current File : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Services/EncryptionService.php |
<?php
/*
* @copyright 2022 Passwords App
*
* @author Marius David Wieschollek
* @license AGPL-3.0
*
* This file is part of the Passwords App
* created by Marius David Wieschollek.
*/
namespace OCA\Passwords\Services;
use Exception;
use OCA\Passwords\Db\Challenge;
use OCA\Passwords\Db\Keychain;
use OCA\Passwords\Db\RevisionInterface;
use OCA\Passwords\Encryption\Challenge\ChallengeEncryptionInterface;
use OCA\Passwords\Encryption\Challenge\SimpleChallengeEncryption;
use OCA\Passwords\Encryption\Keychain\KeychainEncryptionInterface;
use OCA\Passwords\Encryption\Keychain\SseV2KeychainEncryption;
use OCA\Passwords\Encryption\Object\ObjectEncryptionInterface;
use OCA\Passwords\Encryption\Object\SseV1Encryption;
use OCA\Passwords\Encryption\Object\SseV2Encryption;
use OCA\Passwords\Encryption\Object\SseV3Encryption;
use OCA\Passwords\Helper\Settings\UserSettingsHelper;
use OCP\AppFramework\IAppContainer;
/**
* Class EncryptionService
*
* @package OCA\Passwords\Services
*/
class EncryptionService {
const DEFAULT_CSE_ENCRYPTION = 'none';
const DEFAULT_SSE_ENCRYPTION = 'SSEv1r2';
const DEFAULT_SHARE_ENCRYPTION = 'SSSEv1r1';
const CSE_ENCRYPTION_NONE = 'none';
const CSE_ENCRYPTION_V1R1 = 'CSEv1r1';
const SSE_ENCRYPTION_NONE = 'none';
const SSE_ENCRYPTION_V1R1 = 'SSEv1r1';
const SSE_ENCRYPTION_V1R2 = 'SSEv1r2';
const SSE_ENCRYPTION_V2R1 = 'SSEv2r1';
const SSE_ENCRYPTION_V3R1 = 'SSEv3r1';
const SHARE_ENCRYPTION_V1 = 'SSSEv1r1';
/**
* @var array|string[]
*/
protected array $objectMapping
= [
self::SSE_ENCRYPTION_V1R1 => SseV1Encryption::class,
self::SSE_ENCRYPTION_V1R2 => SseV1Encryption::class,
self::SSE_ENCRYPTION_V2R1 => SseV2Encryption::class,
self::SSE_ENCRYPTION_V3R1 => SseV3Encryption::class,
];
/**
* @var string[]
*/
protected array $keychainMapping
= [
Keychain::TYPE_CSE_V1V1 => SseV2KeychainEncryption::class,
Keychain::TYPE_SSE_V2R1 => SseV2KeychainEncryption::class
];
/**
* @var string[]
*/
protected array $challengeMapping
= [
Challenge::TYPE_PWD_V1R1 => SimpleChallengeEncryption::class
];
/**
* @var IAppContainer
*/
private IAppContainer $container;
/**
* @var UserSettingsHelper
*/
protected UserSettingsHelper $userSettings;
/**
* EncryptionService constructor.
*
* @param IAppContainer $container
* @param UserSettingsHelper $userSettings
*/
public function __construct(IAppContainer $container, UserSettingsHelper $userSettings) {
$this->container = $container;
$this->userSettings = $userSettings;
}
/**
* @param RevisionInterface $object
*
* @return RevisionInterface
* @throws Exception
*/
public function encrypt(RevisionInterface $object): RevisionInterface {
if(!$object->_isDecrypted()) return $object;
if($object->getSseType() === self::SSE_ENCRYPTION_NONE) {
$object->_setDecrypted(false);
return $object;
}
$encryption = $this->getObjectEncryptionByType($object->getSseType());
if(!$encryption->isAvailable()) throw new Exception("Object encryption type {$encryption->getType()} is not available");
$encryptedObject = $encryption->encryptObject($object);
$encryptedObject->_setDecrypted(false);
return $encryptedObject;
}
/**
* @param RevisionInterface $object
*
* @return RevisionInterface
* @throws Exception
*/
public function decrypt(RevisionInterface $object): RevisionInterface {
if($object->_isDecrypted()) return $object;
if($object->getSseType() === self::SSE_ENCRYPTION_NONE) {
$object->_setDecrypted(true);
return $object;
}
$encryption = $this->getObjectEncryptionByType($object->getSseType());
if(!$encryption->isAvailable()) throw new Exception("Object encryption type {$encryption->getType()} is not available");
$object = $encryption->decryptObject($object);
$object->_setDecrypted(true);
return $object;
}
/**
* @param Keychain $keychain
*
* @return Keychain
* @throws Exception
*/
public function encryptKeychain(Keychain $keychain): Keychain {
if(!$keychain->_isDecrypted()) return $keychain;
$encryption = $this->getKeychainEncryptionByType($keychain->getType());
if(!$encryption->isAvailable()) throw new Exception("Keychain encryption type {$encryption->getType()} is not available");
$encryptedKeychain = $encryption->encryptKeychain($keychain);
$encryptedKeychain->_setDecrypted(false);
return $encryptedKeychain;
}
/**
* @param Keychain $keychain
*
* @return Keychain
* @throws Exception
*/
public function decryptKeychain(Keychain $keychain): Keychain {
if($keychain->_isDecrypted()) return $keychain;
$encryption = $this->getKeychainEncryptionByType($keychain->getType());
if(!$encryption->isAvailable()) throw new Exception("Keychain encryption type {$encryption->getType()} is not available");
$keychain->_setDecrypted(true);
return $encryption->decryptKeychain($keychain);
}
/**
* @param Challenge $challenge
*
* @return Challenge
* @throws Exception
*/
public function encryptChallenge(Challenge $challenge): Challenge {
if(!$challenge->_isDecrypted()) return $challenge;
$encryption = $this->getChallengeEncryptionByType($challenge->getType());
if(!$encryption->isAvailable()) throw new Exception("Challenge encryption type {$encryption->getType()} is not available");
$encryptedChallenge = $encryption->encryptChallenge($challenge);
$encryptedChallenge->_setDecrypted(false);
return $encryptedChallenge;
}
/**
* @param Challenge $challenge
*
* @return Challenge
* @throws Exception
*/
public function decryptChallenge(Challenge $challenge): Challenge {
if($challenge->_isDecrypted()) return $challenge;
$encryption = $this->getChallengeEncryptionByType($challenge->getType());
if(!$encryption->isAvailable()) throw new Exception("Challenge encryption type {$encryption->getType()} is not available");
$challenge->_setDecrypted(true);
return $encryption->decryptChallenge($challenge);
}
/**
* @param string|null $cseType
*
* @param string|null $userId
*
* @return string
* @throws Exception
*/
public function getDefaultEncryption(string $cseType = null, string $userId = null): string {
$sseMode = $this->userSettings->get('encryption.sse', $userId);
if($sseMode === 0 && $cseType !== self::CSE_ENCRYPTION_NONE) return self::SSE_ENCRYPTION_NONE;
if($sseMode === 1) {
if($this->getObjectEncryptionByType(self::SSE_ENCRYPTION_V3R1)->isAvailable()) {
return self::SSE_ENCRYPTION_V3R1;
}
return self::SSE_ENCRYPTION_V1R2;
}
if($sseMode === 2 && $this->getObjectEncryptionByType(self::SSE_ENCRYPTION_V2R1)->isAvailable()) {
return self::SSE_ENCRYPTION_V2R1;
}
if($this->getObjectEncryptionByType(self::SSE_ENCRYPTION_V3R1)->isAvailable()) {
return self::SSE_ENCRYPTION_V3R1;
}
return self::SSE_ENCRYPTION_V1R2;
}
/**
* @param string $type
*
* @return ObjectEncryptionInterface
* @throws Exception
*/
protected function getObjectEncryptionByType(string $type): ObjectEncryptionInterface {
if(!isset($this->objectMapping[ $type ])) {
throw new Exception("Object encryption type {$type} does not exist");
}
return $this->container->get($this->objectMapping[ $type ]);
}
/**
* @param string $type
*
* @return KeychainEncryptionInterface
* @throws Exception
*/
protected function getKeychainEncryptionByType(string $type): KeychainEncryptionInterface {
if(!isset($this->keychainMapping[ $type ])) {
throw new Exception("Keychain encryption not found for {$type}");
}
return $this->container->get($this->keychainMapping[ $type ]);
}
/**
* @param string $type
*
* @return ChallengeEncryptionInterface
* @throws Exception
*/
protected function getChallengeEncryptionByType(string $type): ChallengeEncryptionInterface {
if(!isset($this->challengeMapping[ $type ])) {
throw new Exception("Challenge encryption not found for {$type}");
}
return $this->container->get($this->challengeMapping[ $type ]);
}
}