Files
nextcloud-ng_backup/tests/Unit/Crypto/KeyRingTest.php
T
dillard 042fdae686
CI / unit (8.2) (push) Has been cancelled
CI / unit (8.3) (push) Has been cancelled
CI / unit (8.4) (push) Has been cancelled
CI / psalm (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / integration (mariadb, 32) (push) Has been cancelled
CI / integration (mariadb, 33) (push) Has been cancelled
CI / integration (mariadb, 34) (push) Has been cancelled
CI / integration (mariadb, 35) (push) Has been cancelled
CI / integration (pgsql, 32) (push) Has been cancelled
CI / integration (pgsql, 33) (push) Has been cancelled
CI / integration (pgsql, 34) (push) Has been cancelled
CI / integration (pgsql, 35) (push) Has been cancelled
CI / integration (sqlite, 32) (push) Has been cancelled
CI / integration (sqlite, 33) (push) Has been cancelled
CI / integration (sqlite, 34) (push) Has been cancelled
CI / integration (sqlite, 35) (push) Has been cancelled
CI / integration-targets (push) Has been cancelled
CI / integration-user (32) (push) Has been cancelled
CI / integration-user (33) (push) Has been cancelled
CI / integration-user (34) (push) Has been cancelled
CI / integration-user (35) (push) Has been cancelled
CI / integration-full-restore (push) Has been cancelled
Review fixes: the longest deletion delay when the location's settings cannot be read, a damaged passphrase slot does not stop the next one
- Unreadable settings or an invalid delay on the location: 365 days, so nothing leaves the Bin sooner than on the old server
- A passphrase change that still cannot reach a location is logged; removing a location clears its flag
- A damaged slot (missing parts, invalid base64) is skipped and the next slot is tried
- Tests: damaged settings scenario, damaged slot, upgrade test checks the migration and the time zone
2026-11-08 18:29:31 +01:00

66 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace OCA\NgBackup\Tests\Unit\Crypto;
use OCA\NgBackup\Crypto\CryptoException;
use OCA\NgBackup\Crypto\KeyRing;
use PHPUnit\Framework\TestCase;
class KeyRingTest extends TestCase {
public function testWrapUnwrapKeepsKeys(): void {
$keys = KeyRing::generate();
$restored = KeyRing::unwrap($keys->wrap('pass phrase'), 'pass phrase');
$this->assertSame($keys->blobId('data'), $restored->blobId('data'));
$this->assertSame($keys->dataKey(), $restored->dataKey());
}
public function testWrongPassphrase(): void {
$wrapped = KeyRing::generate()->wrap('right');
$this->expectException(CryptoException::class);
KeyRing::unwrap($wrapped, 'wrong');
}
public function testBlobIdsAreKeyed(): void {
$this->assertNotSame(KeyRing::generate()->blobId('same'), KeyRing::generate()->blobId('same'));
$k = KeyRing::generate();
$this->assertSame($k->blobId('same'), $k->blobId('same'));
$this->assertMatchesRegularExpression('/^[0-9a-f]{64}$/', $k->blobId('x'));
}
public function testRejectsShortMasterKey(): void {
$this->expectException(\InvalidArgumentException::class);
new KeyRing('short');
}
public function testADamagedSlotDoesNotStopTheNextOne(): void {
$keys = KeyRing::generate();
$broken = $keys->wrap('passphrase in the safe');
$broken['salt'] = '*** not base64 ***';
$field = ['slots' => [
['slot' => 1, 'label' => 'Safe', 'key' => $broken],
['slot' => 2, 'label' => 'Missing parts', 'key' => ['v' => 1]],
['slot' => 3, 'label' => 'CTO', 'key' => $keys->wrap('passphrase of the cto')],
]];
$this->assertSame($keys->blobId('x'), KeyRing::unwrapAny($field, 'passphrase of the cto')->blobId('x'));
$this->expectException(CryptoException::class);
KeyRing::unwrapAny($field, 'passphrase in the safe');
}
public function testAnySlotOpensTheSameKey(): void {
$keys = KeyRing::generate();
$field = ['slots' => [
['slot' => 1, 'label' => 'Safe', 'key' => $keys->wrap('passphrase in the safe')],
['slot' => 2, 'label' => 'CTO', 'key' => $keys->wrap('passphrase of the cto')],
['slot' => 3, 'label' => 'Head of IT', 'key' => $keys->wrap('passphrase head of it')],
]];
foreach (['passphrase in the safe', 'passphrase of the cto', 'passphrase head of it'] as $p) {
$this->assertSame($keys->blobId('x'), KeyRing::unwrapAny($field, $p)->blobId('x'));
}
$this->assertSame($keys->blobId('x'), KeyRing::unwrapAny($keys->wrap('legacy single'), 'legacy single')->blobId('x'));
$this->expectException(CryptoException::class);
KeyRing::unwrapAny($field, 'nobody knows this');
}
}