This commit is contained in:
Bartosz Chyży 2020-06-21 02:07:07 +02:00
parent c2e22ac73f
commit baa2eac499
9 changed files with 141 additions and 40 deletions

View File

@ -1,7 +1,9 @@
using System; using System;
using SafeMessageStorage.Encryption.Hash.Providers; using SafeMessageStorage.Encryption.Hash.Providers;
using SafeMessageStorage.Encryption.Symmetric;
using SafeMessageStorage.Pages; using SafeMessageStorage.Pages;
using SafeMessageStorage.Services.AuthorizationService; using SafeMessageStorage.Services.AuthorizationService;
using SafeMessageStorage.Services.MessageStorageService;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
namespace SafeMessageStorage namespace SafeMessageStorage
@ -12,7 +14,9 @@ namespace SafeMessageStorage
public App() public App()
{ {
InitializeComponent(); InitializeComponent();
MainPage = new NavigationPage(new AuthorizationPage(new AuthorizationService(new Sha256HashProvider()))); var authorizationService = new AuthorizationService(new Sha256HashProvider());
var messageStorageService = new SafeMessageStorageService(authorizationService, new SymmetricEncryptionEngine());
MainPage = new NavigationPage(new AuthorizationPage(authorizationService,messageStorageService));
} }
protected override void OnStart() protected override void OnStart()

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace SafeMessageStorage.Encryption.Symmetric
{
public class SymmetricEncryptionEngine : ISymmetricEncryptionEngine
{
public string Encrypt(string content, string key)
{
byte[] iv = new byte[16];
byte[] array;
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key).Take(16).ToArray();
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
{
streamWriter.Write(content);
}
array = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(array);
}
public string Decrypt(string cipher, string key)
{
byte[] iv = new byte[16];
byte[] buffer = Convert.FromBase64String(cipher);
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key).Take(16).ToArray();
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(buffer))
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
}
}

View File

@ -19,13 +19,13 @@ namespace SafeMessageStorage.Models
} }
public string Id { get; } public string Id { get; set; }
public string Title { get; } public string Title { get; set; }
public string Content { get; } public string Content { get; set; }
public DateTimeOffset TimeOfCreation { get; } public DateTimeOffset TimeOfCreation { get; set; }
} }
} }

View File

@ -13,20 +13,38 @@ namespace SafeMessageStorage.Pages
[XamlCompilation(XamlCompilationOptions.Compile)] [XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AddMessagePage : ContentPage public partial class AddMessagePage : ContentPage
{ {
//private IMessageStorageService _messageStorage; private IMessageStorageService _messageStorage;
public AddMessagePage(/*IMessageStorageService messageStorageService*/) public AddMessagePage(IMessageStorageService messageStorageService)
{ {
InitializeComponent(); InitializeComponent();
_messageStorage = messageStorageService;
} }
private async void Button_OnClicked(object sender, EventArgs e) private async void Button_OnClicked(object sender, EventArgs e)
{ {
if (string.IsNullOrWhiteSpace(TitleEntry.Text))
{
await DisplayAlert("Message not valid", "Title cannot be empty", "ok");
return;
}
if (string.IsNullOrWhiteSpace(ContentEntry.Text))
{
await DisplayAlert("Message not valid", "Content cannot be empty", "ok");
return;
}
var message = new Message(TitleEntry.Text,ContentEntry.Text); var message = new Message(TitleEntry.Text,ContentEntry.Text);
//if(await _messageStorage.SaveMessageAsync(message)) if (await _messageStorage.SaveMessageAsync(message))
MessageAdded?.Invoke(this,message); {
MessageAdded?.Invoke(this, message);
await Navigation.PopAsync(); await Navigation.PopAsync();
}
else
{
await DisplayAlert("Failed", "Unable to add message, try again", "ok");
}
} }
public event EventHandler<Message> MessageAdded; public event EventHandler<Message> MessageAdded;

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using SafeMessageStorage.Services.AuthorizationService; using SafeMessageStorage.Services.AuthorizationService;
using SafeMessageStorage.Services.MessageStorageService;
using SafeMessageStorage.ViewModels; using SafeMessageStorage.ViewModels;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
@ -15,11 +16,13 @@ namespace SafeMessageStorage.Pages
{ {
private AuthorizationPageViewModel _viewModel => this.BindingContext as AuthorizationPageViewModel; private AuthorizationPageViewModel _viewModel => this.BindingContext as AuthorizationPageViewModel;
private IAuthorizationService _authorizationService; private IAuthorizationService _authorizationService;
public AuthorizationPage(IAuthorizationService authorizationService) private IMessageStorageService _messageStorage;
public AuthorizationPage(IAuthorizationService authorizationService, IMessageStorageService messageStorage)
{ {
InitializeComponent(); InitializeComponent();
BindingContext = new AuthorizationPageViewModel(authorizationService); BindingContext = new AuthorizationPageViewModel(authorizationService);
_authorizationService = authorizationService; _authorizationService = authorizationService;
_messageStorage = messageStorage;
_viewModel.AuthorizationFailed += _viewModel_AuthorizationFailed; _viewModel.AuthorizationFailed += _viewModel_AuthorizationFailed;
_viewModel.AuthorizationSucceeded += _viewModel_AuthorizationSucceeded; _viewModel.AuthorizationSucceeded += _viewModel_AuthorizationSucceeded;
@ -38,7 +41,7 @@ namespace SafeMessageStorage.Pages
private async void _viewModel_AuthorizationSucceeded(object sender, EventArgs e) private async void _viewModel_AuthorizationSucceeded(object sender, EventArgs e)
{ {
await Navigation.PushAsync(new MessagesListPage()); await Navigation.PushAsync(new MessagesListPage(_messageStorage));
} }
private async void _viewModel_AuthorizationFailed(object sender, string e) private async void _viewModel_AuthorizationFailed(object sender, string e)

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using SafeMessageStorage.Models; using SafeMessageStorage.Models;
using SafeMessageStorage.Services.MessageStorageService;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
@ -13,12 +14,12 @@ namespace SafeMessageStorage.Pages
public partial class MessageDetailPage : ContentPage public partial class MessageDetailPage : ContentPage
{ {
private string _messageId; private string _messageId;
private IMessageStorageService _messageStorage;
public MessageDetailPage(Message message) public MessageDetailPage(Message message, IMessageStorageService messageStorage)
{ {
InitializeComponent(); InitializeComponent();
_messageId = message.Id; _messageId = message.Id;
_messageStorage = messageStorage;
Title = message.Title; Title = message.Title;
MessageContent.Text = message.Content; MessageContent.Text = message.Content;
@ -27,11 +28,10 @@ namespace SafeMessageStorage.Pages
private async void DeleteMessage() private async void DeleteMessage()
{ {
MessageDeleted?.Invoke(this,_messageId); if (await _messageStorage.DeleteMessageAsync(_messageId))
await Navigation.PopAsync(); await Navigation.PopAsync();
else
await DisplayAlert("Unable to delete messafe", "please try again", "ok");
} }
public event EventHandler<string> MessageDeleted;
} }
} }

View File

@ -4,7 +4,8 @@
xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" mc:Ignorable="d"
x:Class="SafeMessageStorage.Pages.MessagesListPage"> x:Class="SafeMessageStorage.Pages.MessagesListPage"
Title="Messages">
<StackLayout> <StackLayout>
<ListView x:Name="MyListView" <ListView x:Name="MyListView"
ItemsSource="{Binding Messages}" ItemsSource="{Binding Messages}"

View File

@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using SafeMessageStorage.Models; using SafeMessageStorage.Models;
using SafeMessageStorage.Services.MessageStorageService;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
@ -12,27 +13,37 @@ namespace SafeMessageStorage.Pages
[XamlCompilation(XamlCompilationOptions.Compile)] [XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MessagesListPage : ContentPage public partial class MessagesListPage : ContentPage
{ {
private IMessageStorageService _messageStorage;
private bool _initialized;
public ObservableCollection<Message> Messages { get; set; } public ObservableCollection<Message> Messages { get; set; }
public MessagesListPage() public MessagesListPage(IMessageStorageService messageStorage)
{ {
InitializeComponent(); InitializeComponent();
Messages = new ObservableCollection<Message>() _messageStorage = messageStorage;
{ Messages = new ObservableCollection<Message>();
new Message("Siemano","jakas wiadomosc"),
new Message("Kanapka","elo")
};
BindingContext = this; BindingContext = this;
} }
protected override async void OnAppearing()
{
base.OnAppearing();
Messages.Clear();
var messages = await _messageStorage.ReadMessagesAsync();
foreach (var message in messages)
{
Messages.Add(message);
}
}
async void Handle_ItemTapped(object sender, ItemTappedEventArgs e) async void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{ {
if (e.Item == null) if (e.Item == null)
return; return;
var message = ((ListView) sender).SelectedItem as Message; var message = ((ListView) sender).SelectedItem as Message;
var detailPage = new MessageDetailPage(message); var detailPage = new MessageDetailPage(message, _messageStorage);
detailPage.MessageDeleted += (sender, messageId) => OnMessageDeleted(messageId); //detailPage.MessageDeleted += (sender, messageId) => OnMessageDeleted(messageId);
await Navigation.PushAsync(detailPage); await Navigation.PushAsync(detailPage);
////Deselect Item ////Deselect Item
@ -41,17 +52,10 @@ namespace SafeMessageStorage.Pages
private async void Button_OnClicked(object sender, EventArgs e) private async void Button_OnClicked(object sender, EventArgs e)
{ {
var addMessagePage = new AddMessagePage(); var addMessagePage = new AddMessagePage(_messageStorage);
addMessagePage.MessageAdded+= (o, message) => Dispatcher.BeginInvokeOnMainThread(()=>Messages.Add(message)); //addMessagePage.MessageAdded+= (o, message) => Dispatcher.BeginInvokeOnMainThread(()=>Messages.Add(message));
await Navigation.PushAsync(addMessagePage); await Navigation.PushAsync(addMessagePage);
} }
private void OnMessageDeleted(string messageId)
{
var toRemove = Messages.FirstOrDefault(m => m.Id == messageId);
Messages.Remove(toRemove);
}
} }
} }

View File

@ -16,6 +16,12 @@ namespace SafeMessageStorage.Services.MessageStorageService
private ISymmetricEncryptionEngine _encryptionEngine; private ISymmetricEncryptionEngine _encryptionEngine;
private readonly string _messagesKey = "377f2486-d2c3-48a7-b821-45d7314479cd"; private readonly string _messagesKey = "377f2486-d2c3-48a7-b821-45d7314479cd";
public SafeMessageStorageService(IAuthorizationService authorizationService, ISymmetricEncryptionEngine encryptionEngine)
{
_authorizationService = authorizationService;
_encryptionEngine = encryptionEngine;
}
public bool IsStorageEmpty => Xamarin.Essentials.SecureStorage.GetAsync(_messagesKey).Result != null; public bool IsStorageEmpty => Xamarin.Essentials.SecureStorage.GetAsync(_messagesKey).Result != null;
public async Task<bool> SaveMessageAsync(Message message) public async Task<bool> SaveMessageAsync(Message message)
@ -34,10 +40,10 @@ namespace SafeMessageStorage.Services.MessageStorageService
CheckIfAuthorized(); CheckIfAuthorized();
var encryptedMessage =await Xamarin.Essentials.SecureStorage.GetAsync(_messagesKey); var encryptedMessage =await Xamarin.Essentials.SecureStorage.GetAsync(_messagesKey);
if (encryptedMessage == null) if (encryptedMessage == null)
return null; return new List<Message>();
var decryptedMessage = _encryptionEngine.Decrypt(encryptedMessage, _authorizationService.AuthorizedUserHash); var decryptedMessage = _encryptionEngine.Decrypt(encryptedMessage, _authorizationService.AuthorizedUserHash);
return JsonConvert.DeserializeObject<List<Message>>(decryptedMessage); return JsonConvert.DeserializeObject<List<Message>>(decryptedMessage).Where(x=>x.Id!=null);
} }
public async Task<bool> DeleteMessageAsync(string messageId) public async Task<bool> DeleteMessageAsync(string messageId)