implemented an E2E-encrypted Nextcloud push-v2 notification system with support for RSA decryption and signature verification; introduced an iOS Notification Service Extension and native AppDelegate handlers for Talk actions (inline reply and mark-as-read); replaced the legacy notification registration with a new lifecycle managing app passwords and secure keypair storage; added background message handling with tray synchronization and a test notification utility in the settings.

This commit is contained in:
2026-07-04 22:50:18 +02:00
parent 32f7c311bc
commit 74a2ddd17f
56 changed files with 2987 additions and 285 deletions
+39
View File
@@ -0,0 +1,39 @@
import 'package:crypton/crypton.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/push/push_keypair.dart';
void main() {
group('generatePushKeypairPems', () {
test('public PEM matches the Nextcloud SPKI format', () {
final pems = generatePushKeypairPems();
final pem = pems.publicKeyPem;
expect(pem, startsWith('-----BEGIN PUBLIC KEY-----\n'));
expect(pem, endsWith('\n-----END PUBLIC KEY-----'));
// RSA-2048 SPKI base64 wrapped at 64 columns is byte-exactly 450 or 451
// characters — the length Nextcloud validates against.
expect(pem.length, anyOf(450, 451));
// The END marker sits at a fixed offset (header + 392 base64 chars + 6
// embedded newlines = 425, then '\n-----END...').
expect(pem.indexOf('\n-----END PUBLIC KEY-----'), 425);
// Body lines (between the header and footer) wrap at 64 columns.
final body = pem
.split('\n')
.where((l) => !l.startsWith('-----'))
.toList();
for (final line in body.take(body.length - 1)) {
expect(line.length, 64);
}
});
test('private PEM round-trips back into a usable key', () {
final pems = generatePushKeypairPems();
final restored = RSAPrivateKey.fromPEM(pems.privateKeyPem);
final restoredPublicPem = restored.publicKey.toFormattedPEM();
expect(restoredPublicPem, pems.publicKeyPem);
});
});
}