fix: read back sent copies after the sec 5.6 upstream fix, pinned at 2d65d66
This commit is contained in:
parent
52947e153d
commit
d6f4c434fa
36 changed files with 4223 additions and 3118 deletions
|
|
@ -5,8 +5,9 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
|
|||
import "package:smol_mail/data/providers/providers.dart";
|
||||
import "package:smol_mail/shared/utils/format.dart";
|
||||
import "package:smol_mail/shared/utils/snackbar.dart";
|
||||
import "package:smol_mail/smol/address.dart";
|
||||
import "package:smol_mail/smol/errors.dart";
|
||||
import "package:smol_mail/smol/proto.dart";
|
||||
import "package:smol_mail/smol/ui.dart";
|
||||
|
||||
/// The full key, the address to hand out, and any key this one replaced —
|
||||
/// the row can only afford a fingerprint, and §8 turns on the user being able
|
||||
|
|
@ -125,7 +126,7 @@ class _ContactDetailScreenState extends ConsumerState<ContactDetailScreen> {
|
|||
const Divider(height: 1),
|
||||
const SizedBox(height: 20),
|
||||
_field(context, "fingerprint", fingerprint(contact.key)),
|
||||
_field(context, "public key", b32encode(contact.key)),
|
||||
_field(context, "public key", contact.key),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
|
|
@ -162,7 +163,7 @@ class _ContactDetailScreenState extends ConsumerState<ContactDetailScreen> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(fingerprint(entry.key)),
|
||||
Text(b32encode(entry.key),
|
||||
Text(entry.key,
|
||||
style: Theme.of(context).textTheme.labelSmall),
|
||||
Text(
|
||||
"replaced ${formatTime(entry.until ~/ 1000)}",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import "package:smol_mail/presentation/routes/app_router.gr.dart";
|
|||
import "package:smol_mail/presentation/theme/app_colors.dart";
|
||||
import "package:smol_mail/shared/utils/snackbar.dart";
|
||||
import "package:smol_mail/smol/errors.dart";
|
||||
import "package:smol_mail/smol/proto.dart";
|
||||
import "package:smol_mail/smol/ui.dart";
|
||||
|
||||
/// Contacts: the addresses bound to keys, with the trust badge and the number
|
||||
/// of keys each has replaced — the §8 surface for noticing rotations.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import "dart:typed_data";
|
||||
|
||||
import "package:auto_route/auto_route.dart";
|
||||
import "package:flutter/material.dart";
|
||||
|
|
@ -40,7 +39,7 @@ class MessageDetailScreen extends ConsumerWidget {
|
|||
}
|
||||
|
||||
Future<void> _nameSender(BuildContext context, WidgetRef ref,
|
||||
Uint8List senderKey) async {
|
||||
String senderKey) async {
|
||||
final client = ref.read(clientProvider);
|
||||
final controller = TextEditingController();
|
||||
final address = await showDialog<String>(
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import "package:smol_mail/presentation/routes/app_router.gr.dart";
|
|||
import "package:smol_mail/presentation/widgets/primary_button.dart";
|
||||
import "package:smol_mail/presentation/widgets/secondary_button.dart";
|
||||
import "package:smol_mail/presentation/widgets/small_loading_spinner.dart";
|
||||
import "package:smol_mail/smol/crypto.dart";
|
||||
import "package:smol_mail/smol/address.dart";
|
||||
import "package:smol_mail/smol/errors.dart";
|
||||
import "package:smol_mail/smol/proto.dart";
|
||||
import "package:smol_mail/smol/ui.dart";
|
||||
import "package:smol_mail/presentation/theme/app_colors.dart";
|
||||
import "package:smol_mail/shared/utils/snackbar.dart";
|
||||
|
||||
|
|
@ -49,6 +49,10 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
// The backup step's copy of the master is overwritten, not left to the
|
||||
// garbage collector — the honest zeroization Dart allows.
|
||||
createdMaster?.fillRange(0, createdMaster!.length, 0);
|
||||
createdMaster = null;
|
||||
seedController.dispose();
|
||||
restoreAddressController.dispose();
|
||||
addressController.dispose();
|
||||
|
|
@ -81,11 +85,12 @@ class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
|
|||
}
|
||||
}
|
||||
|
||||
void _createIdentity() {
|
||||
Future<void> _createIdentity() async {
|
||||
_clearAbandonedIdentity();
|
||||
final client = ref.read(clientProvider);
|
||||
try {
|
||||
final master = client.createIdentity();
|
||||
final master = await client.createIdentity();
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
createdMaster = master;
|
||||
step = _Step.backup;
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import "package:smol_mail/data/providers/providers.dart";
|
|||
import "package:smol_mail/presentation/routes/app_router.gr.dart";
|
||||
import "package:smol_mail/presentation/theme/app_colors.dart";
|
||||
import "package:smol_mail/shared/utils/snackbar.dart";
|
||||
import "package:smol_mail/smol/crypto.dart";
|
||||
import "package:smol_mail/smol/errors.dart";
|
||||
import "package:smol_mail/smol/proto.dart";
|
||||
import "package:smol_mail/smol/ui.dart";
|
||||
|
||||
/// Identity card, server pins, rotation and the wipe. The seed is the only
|
||||
/// secret; revealing it is always an explicit action.
|
||||
|
|
@ -69,10 +68,11 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
|
|||
// pinned servers into one shareable file; never the seed.
|
||||
Future<void> _export() async {
|
||||
final store = ref.read(storeProvider);
|
||||
final data = store.exportData();
|
||||
// exportData is the sealed gsmol container itself; the file body is its
|
||||
// JSON, already sealed to the master-derived key.
|
||||
final bytes = Uint8List.fromList(utf8.encode(await store.exportData()));
|
||||
final stamp = DateTime.now().toIso8601String().substring(0, 10);
|
||||
final fileName = "kirakira-backup-$stamp.json";
|
||||
final bytes = Uint8List.fromList(utf8.encode(jsonEncode(data)));
|
||||
try {
|
||||
// share_plus has no file-sharing implementation on desktop platforms —
|
||||
// it throws UnimplementedError for Linux/Windows/macOS — so those save
|
||||
|
|
@ -108,8 +108,8 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
|
|||
final path = files.isEmpty ? null : files.single.path;
|
||||
if (path == null) return;
|
||||
try {
|
||||
final data = jsonDecode(File(path).readAsStringSync()) as Map;
|
||||
final summary = await ref.read(storeProvider).importData(data);
|
||||
final summary =
|
||||
await ref.read(storeProvider).importData(File(path).readAsStringSync());
|
||||
ref.read(revisionProvider.notifier).bump();
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
|
|
@ -165,7 +165,7 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
|
|||
ref.read(revisionProvider.notifier).bump();
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("rotated; new key ${b32encode(fresh.publicKey)}")),
|
||||
SnackBar(content: Text("rotated; new key ${fresh.publicKey}")),
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
@ -313,7 +313,7 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
|
|||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(host),
|
||||
subtitle: Text(
|
||||
b32encode(key),
|
||||
key,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.labelSmall,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import "package:smol_mail/presentation/routes/app_router.gr.dart";
|
|||
import "package:smol_mail/presentation/theme/app_colors.dart";
|
||||
import "package:smol_mail/shared/utils/avatar_color.dart";
|
||||
import "package:smol_mail/shared/utils/format.dart";
|
||||
import "package:smol_mail/smol/proto.dart";
|
||||
import "package:smol_mail/smol/store.dart";
|
||||
|
||||
class MessageTile extends ConsumerWidget {
|
||||
|
|
@ -27,7 +26,7 @@ class MessageTile extends ConsumerWidget {
|
|||
who = record.recipient ?? "";
|
||||
} else if (opened.sender != null) {
|
||||
final known = store.addressForKey(opened.sender!);
|
||||
who = known ?? "unknown · ${b32encode(opened.sender!).substring(0, 4)}";
|
||||
who = known ?? "unknown · ${opened.sender!.substring(0, 4)}";
|
||||
} else {
|
||||
who = "?";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import "dart:typed_data";
|
||||
|
||||
import "package:auto_route/auto_route.dart";
|
||||
import "package:flutter/material.dart";
|
||||
|
|
@ -9,8 +8,8 @@ import "package:smol_mail/presentation/routes/app_router.gr.dart";
|
|||
import "package:smol_mail/shared/utils/format.dart";
|
||||
import "package:smol_mail/shared/utils/snackbar.dart";
|
||||
import "package:smol_mail/smol/client.dart";
|
||||
import "package:smol_mail/smol/proto.dart";
|
||||
import "package:smol_mail/smol/store.dart";
|
||||
import "package:smol_mail/smol/ui.dart";
|
||||
|
||||
/// The opened message: trust row (fingerprint and how the sender's key is
|
||||
/// known), frontmatter fields, and the plain body — smol mail has no HTML.
|
||||
|
|
@ -18,7 +17,7 @@ class MessageView extends ConsumerWidget {
|
|||
final String folder;
|
||||
final MailRecord record;
|
||||
final OpenedRecord opened;
|
||||
final void Function(Uint8List senderKey)? onNameSender;
|
||||
final void Function(String senderKey)? onNameSender;
|
||||
|
||||
const MessageView({
|
||||
super.key,
|
||||
|
|
@ -78,7 +77,7 @@ class MessageView extends ConsumerWidget {
|
|||
],
|
||||
if (!isSent && senderKey != null) ...[
|
||||
const SizedBox(height: 10),
|
||||
_keyBlock(context, "${fingerprint(senderKey)}\n${b32encode(senderKey)}"),
|
||||
_keyBlock(context, "${fingerprint(senderKey)}\n$senderKey"),
|
||||
],
|
||||
const SizedBox(height: 18),
|
||||
_field(context, isSent ? "To" : "From",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue