password work

This commit is contained in:
Christien Rioux 2023-09-26 22:32:13 -04:00
parent 9d1eaeed4c
commit 960b8375b5
14 changed files with 77 additions and 182 deletions

View File

@ -101,7 +101,13 @@
},
"enter_pin_dialog": {
"enter_pin": "Enter PIN",
"reenter_pin": "Re-Enter PIN To Confirm"
"reenter_pin": "Re-Enter PIN To Confirm",
"pin_does_not_match": "PIN does not match"
},
"enter_password_dialog": {
"enter_password": "Enter Password",
"reenter_password": "Re-Enter Password To Confirm",
"password_does_not_match": "Password does not match"
},
"contact_list": {
"title": "Contact List",

View File

@ -10,12 +10,12 @@ import '../tools/tools.dart';
class EnterPinDialog extends ConsumerStatefulWidget {
const EnterPinDialog({
this.matchPin,
this.description,
required this.reenter,
required this.description,
super.key,
});
final String? matchPin;
final bool reenter;
final String? description;
@override
@ -25,8 +25,8 @@ class EnterPinDialog extends ConsumerStatefulWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(StringProperty('matchPin', matchPin))
..add(StringProperty('description', description));
..add(StringProperty('description', description))
..add(DiagnosticsProperty<bool>('reenter', reenter));
}
}
@ -77,7 +77,7 @@ class EnterPinDialogState extends ConsumerState<EnterPinDialog> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
widget.matchPin == null
!widget.reenter
? translate('enter_pin_dialog.enter_pin')
: translate('enter_pin_dialog.reenter_pin'),
style: theme.textTheme.titleLarge,
@ -94,23 +94,10 @@ class EnterPinDialogState extends ConsumerState<EnterPinDialog> {
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
// validator: (widget.matchPin != null)
// ? (value) => value == widget.matchPin
// ? null
// : translate('enter_pin_dialog.pin_does_not_match')
// : null,
// onClipboardFound: (value) {
// debugPrint('onClipboardFound: $value');
// pinController.setText(value);
// },
hapticFeedbackType: HapticFeedbackType.lightImpact,
onCompleted: (pin) {
debugPrint('onCompleted: $pin');
Navigator.pop(context, pin);
},
onChanged: (value) {
debugPrint('onChanged: $value');
},
cursor: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
@ -129,13 +116,6 @@ class EnterPinDialogState extends ConsumerState<EnterPinDialog> {
border: Border.all(color: borderColor),
),
),
errorText: '',
errorPinTheme: defaultPinTheme.copyWith(
decoration: BoxDecoration(
color: scale.errorScale.border,
borderRadius: BorderRadius.circular(8),
),
),
).paddingAll(16),
),
if (widget.description != null)

View File

@ -11,6 +11,7 @@ import '../providers/contact.dart';
import '../providers/contact_invite.dart';
import '../tools/tools.dart';
import '../veilid_support/veilid_support.dart';
import 'enter_password.dart';
import 'enter_pin.dart';
import 'profile_widget.dart';
@ -184,22 +185,22 @@ class PasteInviteDialogState extends ConsumerState<PasteInviteDialog> {
}
final pin = await showDialog<String>(
context: context,
builder: (context) =>
EnterPinDialog(description: description));
builder: (context) => EnterPinDialog(
reenter: false, description: description));
if (pin == null) {
return null;
}
encryptionKey = pin;
case EncryptionKeyType.password:
final description =
translate('contact_invite.protected_with_pin');
translate('contact_invite.protected_with_password');
if (!context.mounted) {
return null;
}
final password = await showDialog<String>(
context: context,
builder: (context) =>
EnterPinDialog(description: description));
EnterPasswordDialog(description: description));
if (password == null) {
return null;
}
@ -215,6 +216,7 @@ class PasteInviteDialogState extends ConsumerState<PasteInviteDialog> {
// Check if validation was cancelled
if (validatedContactInvitation == null) {
setState(() {
_pasteTextController.text = '';
_validatingPaste = false;
_validInvitation = null;
});
@ -233,20 +235,22 @@ class PasteInviteDialogState extends ConsumerState<PasteInviteDialog> {
switch (e.type) {
case EncryptionKeyType.none:
errorText = translate('contact_invite.invalid_invitation');
case EncryptionKeyType.password:
errorText = translate('contact_invite.invalid_pin');
case EncryptionKeyType.pin:
errorText = translate('contact_invite.invalid_pin');
case EncryptionKeyType.password:
errorText = translate('contact_invite.invalid_password');
}
if (context.mounted) {
showErrorToast(context, errorText);
}
setState(() {
_pasteTextController.text = '';
_validatingPaste = false;
_validInvitation = null;
});
} on Exception catch (_) {
setState(() {
_pasteTextController.text = '';
_validatingPaste = false;
_validInvitation = null;
});

View File

@ -14,6 +14,7 @@ import '../providers/contact_invite.dart';
import '../tools/tools.dart';
import '../veilid_support/veilid_support.dart';
import 'contact_invitation_display.dart';
import 'enter_password.dart';
import 'enter_pin.dart';
class SendInviteDialog extends ConsumerStatefulWidget {
@ -55,7 +56,8 @@ class SendInviteDialogState extends ConsumerState<SendInviteDialog> {
final description = translate('send_invite_dialog.pin_description');
final pin = await showDialog<String>(
context: context,
builder: (context) => EnterPinDialog(description: description));
builder: (context) =>
EnterPinDialog(reenter: false, description: description));
if (pin == null) {
return;
}
@ -66,7 +68,7 @@ class SendInviteDialogState extends ConsumerState<SendInviteDialog> {
final matchpin = await showDialog<String>(
context: context,
builder: (context) => EnterPinDialog(
matchPin: pin,
reenter: true,
description: description,
));
if (matchpin == null) {
@ -91,11 +93,42 @@ class SendInviteDialogState extends ConsumerState<SendInviteDialog> {
}
Future<void> _onPasswordEncryptionSelected(bool selected) async {
setState(() {
if (selected) {
final description = translate('send_invite_dialog.password_description');
final password = await showDialog<String>(
context: context,
builder: (context) => EnterPasswordDialog(description: description));
if (password == null) {
return;
}
// ignore: use_build_context_synchronously
if (!context.mounted) {
return;
}
final matchpass = await showDialog<String>(
context: context,
builder: (context) => EnterPasswordDialog(
matchPass: password,
description: description,
));
if (matchpass == null) {
return;
} else if (password == matchpass) {
setState(() {
_encryptionKeyType = EncryptionKeyType.password;
_encryptionKey = password;
});
} else {
// ignore: use_build_context_synchronously
if (!context.mounted) {
return;
}
});
showErrorToast(
context, translate('send_invite_dialog.password_does_not_match'));
setState(() {
_encryptionKeyType = EncryptionKeyType.none;
_encryptionKey = '';
});
}
}
Future<void> _onGenerateButtonPressed() async {

View File

@ -1,2 +0,0 @@
export 'loggy.dart';
export 'state_logger.dart';

View File

@ -1,104 +0,0 @@
import 'dart:io' show Platform;
import 'package:ansicolor/ansicolor.dart';
import 'package:flutter/foundation.dart';
import 'package:loggy/loggy.dart';
import '../veilid_support/veilid_support.dart';
String wrapWithLogColor(LogLevel? level, String text) {
// XXX: https://github.com/flutter/flutter/issues/64491
if (!kIsWeb && Platform.isIOS) {
return text;
}
if (level == null) {
return text;
}
final pen = AnsiPen();
ansiColorDisabled = false;
switch (level) {
case LogLevel.error:
pen
..reset()
..red(bold: true);
return pen(text);
case LogLevel.warning:
pen
..reset()
..yellow(bold: true);
return pen(text);
case LogLevel.info:
pen
..reset()
..white(bold: true);
return pen(text);
case LogLevel.debug:
pen
..reset()
..green(bold: true);
return pen(text);
case traceLevel:
pen
..reset()
..blue(bold: true);
return pen(text);
}
return text;
}
extension PrettyPrintLogRecord on LogRecord {
String pretty() {
final lstr =
wrapWithLogColor(level, '[${level.toString().substring(0, 1)}]');
return '$lstr $message';
}
}
class CallbackPrinter extends LoggyPrinter {
CallbackPrinter() : super();
void Function(LogRecord)? callback;
@override
void onLog(LogRecord record) {
debugPrint(record.pretty());
callback?.call(record);
}
void setCallback(void Function(LogRecord)? cb) {
callback = cb;
}
}
CallbackPrinter globalTerminalPrinter = CallbackPrinter();
LogOptions getLogOptions(LogLevel? level) => LogOptions(
level ?? LogLevel.all,
stackTraceLevel: LogLevel.error,
);
class RootLoggy implements LoggyType {
@override
Loggy<RootLoggy> get loggy => Loggy<RootLoggy>('');
}
Loggy get log => Loggy<RootLoggy>('veilidchat');
void initLoggy() {
Loggy.initLoggy(
logPrinter: globalTerminalPrinter,
logOptions: getLogOptions(null),
);
// ignore: do_not_use_environment
const isTrace = String.fromEnvironment('LOG_TRACE') != '';
LogLevel logLevel;
if (isTrace) {
logLevel = traceLevel;
} else {
logLevel = kDebugMode ? LogLevel.debug : LogLevel.info;
}
Loggy('').level = getLogOptions(logLevel);
}

View File

@ -1,22 +0,0 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'loggy.dart';
class StateLogger extends ProviderObserver {
const StateLogger();
@override
void didUpdateProvider(
ProviderBase<Object?> provider,
Object? previousValue,
Object? newValue,
ProviderContainer container,
) {
log.debug('''
{
provider: ${provider.name ?? provider.runtimeType},
oldValue: $previousValue,
newValue: $newValue
}
''');
super.didUpdateProvider(provider, previousValue, newValue, container);
}
}

View File

@ -7,9 +7,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'app.dart';
import 'log/log.dart';
import 'providers/window_control.dart';
import 'tools/theme_service.dart';
import 'tools/tools.dart';
import 'veilid_init.dart';
void main() async {

View File

@ -2,8 +2,8 @@ import 'dart:async';
import 'package:veilid/veilid.dart';
import 'log/log.dart';
import 'providers/connection_state.dart';
import 'tools/tools.dart';
import 'veilid_support/src/config.dart';
import 'veilid_support/src/veilid_log.dart';

View File

@ -15,7 +15,6 @@ import '../proto/proto.dart'
ContactResponse,
SignedContactInvitation,
SignedContactResponse;
import '../log/log.dart';
import '../tools/tools.dart';
import '../veilid_support/veilid_support.dart';
import 'account.dart';
@ -345,7 +344,7 @@ Future<ValidContactInvitation?> validateContactInvitation(
final contactRequestInboxKey =
proto.TypedKeyProto.fromProto(contactInvitation.contactRequestInboxKey);
late final ValidContactInvitation out;
ValidContactInvitation? out;
final pool = await DHTRecordPool.instance();
final cs = await pool.veilid.getCryptoSystem(contactRequestInboxKey.kind);
@ -365,14 +364,20 @@ Future<ValidContactInvitation?> validateContactInvitation(
// Decrypt contact request private
final encryptionKeyType =
EncryptionKeyType.fromProto(contactRequest!.encryptionKeyType);
final writerSecret = await getEncryptionKeyCallback(cs, encryptionKeyType,
Uint8List.fromList(contactInvitation.writerSecret));
late final SharedSecret? writerSecret;
try {
writerSecret = await getEncryptionKeyCallback(cs, encryptionKeyType,
Uint8List.fromList(contactInvitation.writerSecret));
} on Exception catch (_) {
throw ContactInviteInvalidKeyException(encryptionKeyType);
}
if (writerSecret == null) {
return null;
}
final contactRequestPrivateBytes = await cs.decryptAeadWithNonce(
Uint8List.fromList(contactRequest.private), writerSecret);
final contactRequestPrivate =
proto.ContactRequestPrivate.fromBuffer(contactRequestPrivateBytes);
final contactIdentityMasterRecordKey = proto.TypedKeyProto.fromProto(
@ -385,12 +390,8 @@ Future<ValidContactInvitation?> validateContactInvitation(
// Verify
final signature = proto.SignatureProto.fromProto(
signedContactInvitation.identitySignature);
try {
await cs.verify(contactIdentityMaster.identityPublicKey,
contactInvitationBytes, signature);
} on Exception catch (_) {
throw ContactInviteInvalidKeyException(encryptionKeyType);
}
await cs.verify(contactIdentityMaster.identityPublicKey,
contactInvitationBytes, signature);
final writer = KeyPair(
key: proto.CryptoKeyProto.fromProto(contactRequestPrivate.writerKey),

View File

@ -6,7 +6,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../proto/proto.dart' as proto;
import '../proto/proto.dart' show Conversation, Message;
import '../log/loggy.dart';
import '../tools/tools.dart';
import '../veilid_init.dart';
import '../veilid_support/veilid_support.dart';
import 'account.dart';

View File

@ -5,7 +5,6 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../entities/entities.dart';
import '../proto/proto.dart' as proto;
import '../log/loggy.dart';
import '../tools/tools.dart';
import '../veilid_init.dart';
import '../veilid_support/veilid_support.dart';

View File

@ -4,7 +4,6 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../entities/entities.dart';
import '../log/loggy.dart';
import '../tools/tools.dart';
import '../veilid_init.dart';
import '../veilid_support/veilid_support.dart';

View File

@ -1,8 +1,10 @@
export 'animations.dart';
export 'external_stream_state.dart';
export 'loggy.dart';
export 'phono_byte.dart';
export 'radix_generator.dart';
export 'responsive.dart';
export 'secret_crypto.dart';
export 'state_logger.dart';
export 'theme_service.dart';
export 'widget_helpers.dart';