159 lines
4.8 KiB
Dart
159 lines
4.8 KiB
Dart
// Author: Hugo Pointcheval
|
|
// Email: git@pcl.ovh
|
|
// -----
|
|
// File: cipher_page.dart
|
|
// Created Date: 28/12/2021 13:33:15
|
|
// Last Modified: 25/05/2022 10:49:30
|
|
// -----
|
|
// Copyright (c) 2021
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:native_crypto/native_crypto.dart';
|
|
import 'package:native_crypto_example/widgets/button.dart';
|
|
|
|
import '../session.dart';
|
|
import '../utils.dart';
|
|
import '../widgets/output.dart';
|
|
|
|
// ignore: must_be_immutable
|
|
class CipherPage extends ConsumerWidget {
|
|
CipherPage({Key? key}) : super(key: key);
|
|
|
|
final Output keyContent = Output();
|
|
final Output encryptionStatus = Output();
|
|
final Output decryptionStatus = Output();
|
|
|
|
final TextEditingController _plainTextController = TextEditingController();
|
|
CipherText? cipherText;
|
|
|
|
Future<void> _encrypt(WidgetRef ref, Cipher cipher) async {
|
|
Session state = ref.read(sessionProvider.state).state;
|
|
final plainText = _plainTextController.text.trim();
|
|
|
|
if (state.secretKey.bytes.isEmpty) {
|
|
encryptionStatus
|
|
.print('No SecretKey!\nGo in Key tab and generate or derive one.');
|
|
} else if (plainText.isEmpty) {
|
|
encryptionStatus.print('Entry is empty');
|
|
} else {
|
|
var stringToBytes = plainText.toBytes();
|
|
cipherText = await cipher.encrypt(stringToBytes);
|
|
encryptionStatus.print('String successfully encrypted.\n');
|
|
encryptionStatus.append("Nonce: " +
|
|
cipherText!.iv.toString() +
|
|
"\nData: " +
|
|
cipherText!.data.toString() +
|
|
"\nTag: " +
|
|
cipherText!.tag.toString());
|
|
}
|
|
}
|
|
|
|
Future<void> _alter() async {
|
|
if (cipherText == null) {
|
|
decryptionStatus.print('Encrypt before altering CipherText!');
|
|
} else {
|
|
// Add 1 to the first byte
|
|
Uint8List _altered = cipherText!.data;
|
|
_altered[0] += 1;
|
|
// Recreate cipher text with altered data
|
|
cipherText = CipherText(cipherText!.iv, _altered, cipherText!.tag);
|
|
encryptionStatus.print('String successfully encrypted.\n');
|
|
encryptionStatus.append("Nonce: " +
|
|
cipherText!.iv.toString() +
|
|
"\nData: " +
|
|
cipherText!.data.toString() +
|
|
"\nTag: " +
|
|
cipherText!.tag.toString());
|
|
decryptionStatus.print('CipherText altered!\nDecryption will fail.');
|
|
}
|
|
}
|
|
|
|
void _decrypt(WidgetRef ref, Cipher cipher) async {
|
|
Session state = ref.read(sessionProvider.state).state;
|
|
|
|
if (state.secretKey.bytes.isEmpty) {
|
|
decryptionStatus
|
|
.print('No SecretKey!\nGo in Key tab and generate or derive one.');
|
|
} else if (cipherText == null) {
|
|
decryptionStatus.print('Encrypt before decrypting!');
|
|
} else {
|
|
try {
|
|
Uint8List plainText = await cipher.decrypt(cipherText!);
|
|
var bytesToString = plainText.toStr();
|
|
decryptionStatus
|
|
.print('String successfully decrypted:\n\n$bytesToString');
|
|
} on NativeCryptoException catch (e) {
|
|
decryptionStatus.print(e.message ?? 'Decryption failed!');
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
Session state = ref.read(sessionProvider.state).state;
|
|
if (state.secretKey.bytes.isEmpty) {
|
|
keyContent
|
|
.print('No SecretKey!\nGo in Key tab and generate or derive one.');
|
|
return SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
const Align(
|
|
child: Text("Secret Key"),
|
|
alignment: Alignment.centerLeft,
|
|
),
|
|
keyContent,
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
keyContent.print(state.secretKey.bytes.toString());
|
|
|
|
AES cipher = AES(state.secretKey, AESMode.gcm);
|
|
return SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
const Align(
|
|
child: Text("Secret Key"),
|
|
alignment: Alignment.centerLeft,
|
|
),
|
|
keyContent,
|
|
TextField(
|
|
controller: _plainTextController,
|
|
decoration: const InputDecoration(
|
|
hintText: 'Plain text',
|
|
),
|
|
),
|
|
Button(
|
|
() => _encrypt(ref, cipher),
|
|
"Encrypt",
|
|
),
|
|
encryptionStatus,
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
Button(
|
|
_alter,
|
|
"Alter cipher",
|
|
),
|
|
Button(
|
|
() => _decrypt(ref, cipher),
|
|
"Decrypt",
|
|
),
|
|
],
|
|
),
|
|
decryptionStatus,
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|