Skip to content

Commit 7e15dee

Browse files
committed
feat: Cache user keys
Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
1 parent e4ed547 commit 7e15dee

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

lib/private/Security/IdentityProof/Manager.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use OC\Files\AppData\Factory;
1212
use OCP\Files\IAppData;
1313
use OCP\Files\NotFoundException;
14+
use OCP\ICache;
15+
use OCP\ICacheFactory;
1416
use OCP\IConfig;
1517
use OCP\IUser;
1618
use OCP\Security\ICrypto;
@@ -19,13 +21,17 @@
1921
class Manager {
2022
private IAppData $appData;
2123

24+
protected ICache $cache;
25+
2226
public function __construct(
2327
Factory $appDataFactory,
2428
private ICrypto $crypto,
2529
private IConfig $config,
2630
private LoggerInterface $logger,
31+
private ICacheFactory $cacheFactory,
2732
) {
2833
$this->appData = $appDataFactory->get('identityproof');
34+
$this->cache = $this->cacheFactory->createDistributed('identityproof::');
2935
}
3036

3137
/**
@@ -96,12 +102,24 @@ protected function generateKey(string $id, array $options = []): Key {
96102
*/
97103
protected function retrieveKey(string $id): Key {
98104
try {
105+
$cachedPublicKey = $this->cache->get($id . '-public');
106+
$cachedPrivateKey = $this->cache->get($id . '-private');
107+
108+
if ($cachedPublicKey !== null && $cachedPrivateKey !== null) {
109+
$decryptedPrivateKey = $this->crypto->decrypt($cachedPrivateKey);
110+
111+
return new Key($cachedPublicKey, $decryptedPrivateKey);
112+
}
113+
99114
$folder = $this->appData->getFolder($id);
100-
$privateKey = $this->crypto->decrypt(
101-
$folder->getFile('private')->getContent()
102-
);
115+
$privateKey = $folder->getFile('private')->getContent();
103116
$publicKey = $folder->getFile('public')->getContent();
104-
return new Key($publicKey, $privateKey);
117+
118+
$this->cache->set($id . '-public', $publicKey);
119+
$this->cache->set($id . '-private', $privateKey);
120+
121+
$decryptedPrivateKey = $this->crypto->decrypt($privateKey);
122+
return new Key($publicKey, $decryptedPrivateKey);
105123
} catch (\Exception $e) {
106124
return $this->generateKey($id);
107125
}

tests/lib/Security/IdentityProof/ManagerTest.php

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use OCP\Files\IAppData;
1717
use OCP\Files\SimpleFS\ISimpleFile;
1818
use OCP\Files\SimpleFS\ISimpleFolder;
19+
use OCP\ICache;
20+
use OCP\ICacheFactory;
1921
use OCP\IConfig;
2022
use OCP\IUser;
2123
use OCP\Security\ICrypto;
@@ -36,6 +38,10 @@ class ManagerTest extends TestCase {
3638
private $config;
3739
/** @var LoggerInterface|MockObject */
3840
private $logger;
41+
/** @var LoggerInterface|ICacheFactory */
42+
private $cacheFactory;
43+
/** @var LoggerInterface|ICache */
44+
private $cache;
3945

4046
protected function setUp(): void {
4147
parent::setUp();
@@ -49,6 +55,12 @@ protected function setUp(): void {
4955
->with('identityproof')
5056
->willReturn($this->appData);
5157
$this->logger = $this->createMock(LoggerInterface::class);
58+
$this->cacheFactory = $this->createMock(ICacheFactory::class);
59+
$this->cache = $this->createMock(ICache::class);
60+
61+
$this->cacheFactory->expects($this->any())
62+
->method('createDistributed')
63+
->willReturn($this->cache);
5264

5365
$this->crypto = $this->createMock(ICrypto::class);
5466
$this->manager = $this->getManager(['generateKeyPair']);
@@ -66,15 +78,17 @@ protected function getManager($setMethods = []) {
6678
$this->factory,
6779
$this->crypto,
6880
$this->config,
69-
$this->logger
81+
$this->logger,
82+
$this->cacheFactory,
7083
);
7184
} else {
7285
return $this->getMockBuilder(Manager::class)
7386
->setConstructorArgs([
7487
$this->factory,
7588
$this->crypto,
7689
$this->config,
77-
$this->logger
90+
$this->logger,
91+
$this->cacheFactory,
7892
])
7993
->onlyMethods($setMethods)
8094
->getMock();
@@ -115,6 +129,28 @@ public function testGetKeyWithExistingKey(): void {
115129
->method('getFolder')
116130
->with('user-MyUid')
117131
->willReturn($folder);
132+
$this->cache->expects($this->exactly(2))
133+
->method('get')
134+
->willReturnOnConsecutiveCalls(null, null);
135+
136+
$expected = new Key('MyPublicKey', 'MyPrivateKey');
137+
$this->assertEquals($expected, $this->manager->getKey($user));
138+
}
139+
140+
public function testGetKeyWithExistingKeyCached(): void {
141+
$user = $this->createMock(IUser::class);
142+
$user
143+
->expects($this->once())
144+
->method('getUID')
145+
->willReturn('MyUid');
146+
$this->crypto
147+
->expects($this->once())
148+
->method('decrypt')
149+
->with('EncryptedPrivateKey')
150+
->willReturn('MyPrivateKey');
151+
$this->cache->expects($this->exactly(2))
152+
->method('get')
153+
->willReturnOnConsecutiveCalls('MyPublicKey', 'EncryptedPrivateKey');
118154

119155
$expected = new Key('MyPublicKey', 'MyPrivateKey');
120156
$this->assertEquals($expected, $this->manager->getKey($user));

0 commit comments

Comments
 (0)