diff options
author | Marcel Müller <marcel-mueller@gmx.de> | 2025-08-01 20:50:52 +0200 |
---|---|---|
committer | Marcel Müller <marcel-mueller@gmx.de> | 2025-08-01 22:15:48 +0200 |
commit | 7e15dee9dfbbdf425ad3f3ef34fef2e6c38d8df9 (patch) | |
tree | b272fba42bd273d01d0369085a51ebac8c349a1d | |
parent | e4ed547bc6ab597d640bdec3fa4b8d16df53f98e (diff) | |
download | nextcloud-server-feat/noid/cache-user-keys.tar.gz nextcloud-server-feat/noid/cache-user-keys.zip |
feat: Cache user keysfeat/noid/cache-user-keys
Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
-rw-r--r-- | lib/private/Security/IdentityProof/Manager.php | 26 | ||||
-rw-r--r-- | tests/lib/Security/IdentityProof/ManagerTest.php | 40 |
2 files changed, 60 insertions, 6 deletions
diff --git a/lib/private/Security/IdentityProof/Manager.php b/lib/private/Security/IdentityProof/Manager.php index 935c18bb81d..c16b8314beb 100644 --- a/lib/private/Security/IdentityProof/Manager.php +++ b/lib/private/Security/IdentityProof/Manager.php @@ -11,6 +11,8 @@ namespace OC\Security\IdentityProof; use OC\Files\AppData\Factory; use OCP\Files\IAppData; use OCP\Files\NotFoundException; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IUser; use OCP\Security\ICrypto; @@ -19,13 +21,17 @@ use Psr\Log\LoggerInterface; class Manager { private IAppData $appData; + protected ICache $cache; + public function __construct( Factory $appDataFactory, private ICrypto $crypto, private IConfig $config, private LoggerInterface $logger, + private ICacheFactory $cacheFactory, ) { $this->appData = $appDataFactory->get('identityproof'); + $this->cache = $this->cacheFactory->createDistributed('identityproof::'); } /** @@ -96,12 +102,24 @@ class Manager { */ protected function retrieveKey(string $id): Key { try { + $cachedPublicKey = $this->cache->get($id . '-public'); + $cachedPrivateKey = $this->cache->get($id . '-private'); + + if ($cachedPublicKey !== null && $cachedPrivateKey !== null) { + $decryptedPrivateKey = $this->crypto->decrypt($cachedPrivateKey); + + return new Key($cachedPublicKey, $decryptedPrivateKey); + } + $folder = $this->appData->getFolder($id); - $privateKey = $this->crypto->decrypt( - $folder->getFile('private')->getContent() - ); + $privateKey = $folder->getFile('private')->getContent(); $publicKey = $folder->getFile('public')->getContent(); - return new Key($publicKey, $privateKey); + + $this->cache->set($id . '-public', $publicKey); + $this->cache->set($id . '-private', $privateKey); + + $decryptedPrivateKey = $this->crypto->decrypt($privateKey); + return new Key($publicKey, $decryptedPrivateKey); } catch (\Exception $e) { return $this->generateKey($id); } diff --git a/tests/lib/Security/IdentityProof/ManagerTest.php b/tests/lib/Security/IdentityProof/ManagerTest.php index 445158e8a23..9703d09f506 100644 --- a/tests/lib/Security/IdentityProof/ManagerTest.php +++ b/tests/lib/Security/IdentityProof/ManagerTest.php @@ -16,6 +16,8 @@ use OC\Security\IdentityProof\Manager; use OCP\Files\IAppData; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IUser; use OCP\Security\ICrypto; @@ -36,6 +38,10 @@ class ManagerTest extends TestCase { private $config; /** @var LoggerInterface|MockObject */ private $logger; + /** @var LoggerInterface|ICacheFactory */ + private $cacheFactory; + /** @var LoggerInterface|ICache */ + private $cache; protected function setUp(): void { parent::setUp(); @@ -49,6 +55,12 @@ class ManagerTest extends TestCase { ->with('identityproof') ->willReturn($this->appData); $this->logger = $this->createMock(LoggerInterface::class); + $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->cache = $this->createMock(ICache::class); + + $this->cacheFactory->expects($this->any()) + ->method('createDistributed') + ->willReturn($this->cache); $this->crypto = $this->createMock(ICrypto::class); $this->manager = $this->getManager(['generateKeyPair']); @@ -66,7 +78,8 @@ class ManagerTest extends TestCase { $this->factory, $this->crypto, $this->config, - $this->logger + $this->logger, + $this->cacheFactory, ); } else { return $this->getMockBuilder(Manager::class) @@ -74,7 +87,8 @@ class ManagerTest extends TestCase { $this->factory, $this->crypto, $this->config, - $this->logger + $this->logger, + $this->cacheFactory, ]) ->onlyMethods($setMethods) ->getMock(); @@ -115,6 +129,28 @@ class ManagerTest extends TestCase { ->method('getFolder') ->with('user-MyUid') ->willReturn($folder); + $this->cache->expects($this->exactly(2)) + ->method('get') + ->willReturnOnConsecutiveCalls(null, null); + + $expected = new Key('MyPublicKey', 'MyPrivateKey'); + $this->assertEquals($expected, $this->manager->getKey($user)); + } + + public function testGetKeyWithExistingKeyCached(): void { + $user = $this->createMock(IUser::class); + $user + ->expects($this->once()) + ->method('getUID') + ->willReturn('MyUid'); + $this->crypto + ->expects($this->once()) + ->method('decrypt') + ->with('EncryptedPrivateKey') + ->willReturn('MyPrivateKey'); + $this->cache->expects($this->exactly(2)) + ->method('get') + ->willReturnOnConsecutiveCalls('MyPublicKey', 'EncryptedPrivateKey'); $expected = new Key('MyPublicKey', 'MyPrivateKey'); $this->assertEquals($expected, $this->manager->getKey($user)); |