Skip to content

Commit 5e6532d

Browse files
committed
feat: Cache user keys
Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
1 parent 98fb18f commit 5e6532d

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
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: 47 additions & 14 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;
@@ -24,18 +26,14 @@
2426
use Test\TestCase;
2527

2628
class ManagerTest extends TestCase {
27-
/** @var Factory|MockObject */
28-
private $factory;
29-
/** @var IAppData|MockObject */
30-
private $appData;
31-
/** @var ICrypto|MockObject */
32-
private $crypto;
33-
/** @var Manager|MockObject */
34-
private $manager;
35-
/** @var IConfig|MockObject */
36-
private $config;
37-
/** @var LoggerInterface|MockObject */
38-
private $logger;
29+
private Factory&MockObject $factory;
30+
private IAppData&MockObject $appData;
31+
private ICrypto&MockObject $crypto;
32+
private Manager&MockObject $manager;
33+
private IConfig&MockObject $config;
34+
private LoggerInterface&MockObject $logger;
35+
private ICacheFactory&MockObject $cacheFactory;
36+
private ICache&MockObject $cache;
3937

4038
protected function setUp(): void {
4139
parent::setUp();
@@ -49,6 +47,12 @@ protected function setUp(): void {
4947
->with('identityproof')
5048
->willReturn($this->appData);
5149
$this->logger = $this->createMock(LoggerInterface::class);
50+
$this->cacheFactory = $this->createMock(ICacheFactory::class);
51+
$this->cache = $this->createMock(ICache::class);
52+
53+
$this->cacheFactory->expects($this->any())
54+
->method('createDistributed')
55+
->willReturn($this->cache);
5256

5357
$this->crypto = $this->createMock(ICrypto::class);
5458
$this->manager = $this->getManager(['generateKeyPair']);
@@ -66,15 +70,17 @@ protected function getManager($setMethods = []) {
6670
$this->factory,
6771
$this->crypto,
6872
$this->config,
69-
$this->logger
73+
$this->logger,
74+
$this->cacheFactory,
7075
);
7176
} else {
7277
return $this->getMockBuilder(Manager::class)
7378
->setConstructorArgs([
7479
$this->factory,
7580
$this->crypto,
7681
$this->config,
77-
$this->logger
82+
$this->logger,
83+
$this->cacheFactory,
7884
])->setMethods($setMethods)->getMock();
7985
}
8086
}
@@ -117,6 +123,33 @@ public function testGetKeyWithExistingKey(): void {
117123
->method('getFolder')
118124
->with('user-MyUid')
119125
->willReturn($folder);
126+
$this->cache
127+
->expects($this->exactly(2))
128+
->method('get')
129+
->willReturn(null);
130+
131+
$expected = new Key('MyPublicKey', 'MyPrivateKey');
132+
$this->assertEquals($expected, $this->manager->getKey($user));
133+
}
134+
135+
public function testGetKeyWithExistingKeyCached(): void {
136+
$user = $this->createMock(IUser::class);
137+
$user
138+
->expects($this->once())
139+
->method('getUID')
140+
->willReturn('MyUid');
141+
$this->crypto
142+
->expects($this->once())
143+
->method('decrypt')
144+
->with('EncryptedPrivateKey')
145+
->willReturn('MyPrivateKey');
146+
$this->cache
147+
->expects($this->exactly(2))
148+
->method('get')
149+
->willReturnMap([
150+
['user-MyUid-public', 'MyPublicKey'],
151+
['user-MyUid-private', 'EncryptedPrivateKey'],
152+
]);
120153

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

0 commit comments

Comments
 (0)