Skip to content

Commit 4870486

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

File tree

2 files changed

+65
-6
lines changed

2 files changed

+65
-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: 43 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,33 @@ public function testGetKeyWithExistingKey(): void {
115129
->method('getFolder')
116130
->with('user-MyUid')
117131
->willReturn($folder);
132+
$this->cache
133+
->expects($this->exactly(2))
134+
->method('get')
135+
->willReturn(null);
136+
137+
$expected = new Key('MyPublicKey', 'MyPrivateKey');
138+
$this->assertEquals($expected, $this->manager->getKey($user));
139+
}
140+
141+
public function testGetKeyWithExistingKeyCached(): void {
142+
$user = $this->createMock(IUser::class);
143+
$user
144+
->expects($this->once())
145+
->method('getUID')
146+
->willReturn('MyUid');
147+
$this->crypto
148+
->expects($this->once())
149+
->method('decrypt')
150+
->with('EncryptedPrivateKey')
151+
->willReturn('MyPrivateKey');
152+
$this->cache
153+
->expects($this->exactly(2))
154+
->method('get')
155+
->willReturnMap([
156+
['user-MyUid-public', 'MyPublicKey'],
157+
['user-MyUid-private', 'EncryptedPrivateKey'],
158+
]);
118159

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

0 commit comments

Comments
 (0)