MessageStore

This commit is contained in:
Bartosz Chyży 2020-06-07 15:19:24 +02:00
parent ff98f1a5c1
commit 390fd66d97
10 changed files with 91 additions and 22 deletions

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SafeMessageStorage.Encryption.Symmetric
{
public interface ISymmetricEncryptionEngine
{
string Encrypt(string content, string key);
string Decrypt(string cipher, string key);
}
}

View File

@ -5,7 +5,7 @@
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.AuthorizationPage" x:Class="SafeMessageStorage.Pages.AuthorizationPage"
Title="Authorize"> Title="AuthorizeAsync">
<ContentPage.Content> <ContentPage.Content>
<StackLayout VerticalOptions="CenterAndExpand" Padding="40"> <StackLayout VerticalOptions="CenterAndExpand" Padding="40">
<Label Text="Enter your security code" <Label Text="Enter your security code"
@ -14,7 +14,7 @@
<Label x:Name="ErrorMessageLabel" <Label x:Name="ErrorMessageLabel"
TextColor="#d22" TextColor="#d22"
Margin="0,10" HorizontalOptions="Center"/> Margin="0,10" HorizontalOptions="Center"/>
<Button Text="Authorize" Command="{Binding AuthorizeCommand}"/> <Button Text="AuthorizeAsync" Command="{Binding AuthorizeCommand}"/>
</StackLayout> </StackLayout>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View File

@ -6,12 +6,12 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Xamarin.Forms" Version="4.6.0.847" /> <PackageReference Include="Xamarin.Forms" Version="4.6.0.847" />
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" /> <PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Encryption\Symmetric\" />
<Folder Include="Views\" /> <Folder Include="Views\" />
</ItemGroup> </ItemGroup>

View File

@ -8,7 +8,7 @@ namespace SafeMessageStorage.Services.AuthorizationService
{ {
public class AuthorizationService : IAuthorizationService public class AuthorizationService : IAuthorizationService
{ {
private readonly string _passwordKey = "passwordGUID"; private readonly string _passwordKey = "86d9ee32-c00e-4b18-bb1b-a4f7d9e23ec9";
private readonly IHashProvider _hashProvider; private readonly IHashProvider _hashProvider;
public AuthorizationService(IHashProvider hashProvider) public AuthorizationService(IHashProvider hashProvider)
@ -17,22 +17,27 @@ namespace SafeMessageStorage.Services.AuthorizationService
} }
public bool IsAuthorized { get; private set; } public bool IsAuthorized { get; private set; }
public string AuthorizedUserHash { get; private set; }
public bool IsPasswordSet => Xamarin.Essentials.SecureStorage.GetAsync(_passwordKey).Result != null; public bool IsPasswordSet => Xamarin.Essentials.SecureStorage.GetAsync(_passwordKey).Result != null;
public async Task<bool> Authorize(string password) public async Task<bool> AuthorizeAsync(string password)
{ {
var keyChainPassword = await Xamarin.Essentials.SecureStorage.GetAsync(_passwordKey); var keyChainPassword = await Xamarin.Essentials.SecureStorage.GetAsync(_passwordKey);
var result = keyChainPassword?.Equals(_hashProvider.GetHashString(password)) ?? false; var result = keyChainPassword?.Equals(_hashProvider.GetHashString(password)) ?? false;
IsAuthorized = result; IsAuthorized = result;
AuthorizedUserHash = IsAuthorized ? keyChainPassword : null;
return result; return result;
} }
public Task<bool> Deauthorize() public Task<bool> DeauthorizeAsync()
{ {
IsAuthorized = false; IsAuthorized = false;
AuthorizedUserHash = null;
return Task.FromResult(true); return Task.FromResult(true);
} }
public async Task<bool> ChangePassword(string currentPassword, string newPassword) public async Task<bool> ChangePasswordAsync(string currentPassword, string newPassword)
{ {
var keyChainPassword = await Xamarin.Essentials.SecureStorage.GetAsync(_passwordKey); var keyChainPassword = await Xamarin.Essentials.SecureStorage.GetAsync(_passwordKey);
var passwordMatch = keyChainPassword?.Equals(_hashProvider.GetHashString(currentPassword)) ?? true; var passwordMatch = keyChainPassword?.Equals(_hashProvider.GetHashString(currentPassword)) ?? true;

View File

@ -8,18 +8,19 @@ namespace SafeMessageStorage.Services.AuthorizationService
public class AuthorizationServiceMOCK : IAuthorizationService public class AuthorizationServiceMOCK : IAuthorizationService
{ {
public bool IsAuthorized => false; public bool IsAuthorized => false;
public string AuthorizedUserHash => "kanapka";
public bool IsPasswordSet => false; public bool IsPasswordSet => false;
public Task<bool> Authorize(string password) public Task<bool> AuthorizeAsync(string password)
{ {
return Task.FromResult(false); return Task.FromResult(false);
} }
public Task<bool> Deauthorize() public Task<bool> DeauthorizeAsync()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<bool> ChangePassword(string currentPassword, string newPassword) public Task<bool> ChangePasswordAsync(string currentPassword, string newPassword)
{ {
return Task.FromResult(true); return Task.FromResult(true);
} }

View File

@ -9,12 +9,14 @@ namespace SafeMessageStorage.Services.AuthorizationService
{ {
bool IsAuthorized { get; } bool IsAuthorized { get; }
string AuthorizedUserHash { get; }
bool IsPasswordSet { get; } bool IsPasswordSet { get; }
Task<bool> Authorize(string password); Task<bool> AuthorizeAsync(string password);
Task<bool> Deauthorize(); Task<bool> DeauthorizeAsync();
Task<bool> ChangePassword(string currentPassword, string newPassword); Task<bool> ChangePasswordAsync(string currentPassword, string newPassword);
} }
} }

View File

@ -8,15 +8,12 @@ namespace SafeMessageStorage.Services.MessageStorageService
{ {
public interface IMessageStorageService public interface IMessageStorageService
{ {
Task<bool> IsStorageEmpty { get; } bool IsStorageEmpty { get; }
Task<bool> SaveMessage(Message message);
Task<Message> ReadMessage();
Task<bool> DeleteMessage();
Task<bool> SaveMessageAsync(Message message);
Task<Message> ReadMessageAsync();
Task<bool> DeleteMessageAsync();
} }
} }

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using SafeMessageStorage.Encryption.Symmetric;
using SafeMessageStorage.Models;
using SafeMessageStorage.Services.AuthorizationService;
namespace SafeMessageStorage.Services.MessageStorageService
{
public class SafeMessageStorageService : IMessageStorageService
{
private IAuthorizationService _authorizationService;
private ISymmetricEncryptionEngine _encryptionEngine;
private readonly string _messageKey = "377f2486-d2c3-48a7-b821-45d7314479cd";
public bool IsStorageEmpty => Xamarin.Essentials.SecureStorage.GetAsync(_messageKey).Result != null;
public async Task<bool> SaveMessageAsync(Message message)
{
CheckIfAuthorized();
var encrypyedMessage = _encryptionEngine.Encrypt(JsonConvert.SerializeObject(message), _authorizationService.AuthorizedUserHash);
await Xamarin.Essentials.SecureStorage.SetAsync(_messageKey, encrypyedMessage);
return true;
}
public async Task<Message> ReadMessageAsync()
{
CheckIfAuthorized();
var encryptedMessage =await Xamarin.Essentials.SecureStorage.GetAsync(_messageKey);
if (encryptedMessage == null)
return null;
var decryptedMessage = _encryptionEngine.Decrypt(encryptedMessage, _authorizationService.AuthorizedUserHash);
return JsonConvert.DeserializeObject<Message>(decryptedMessage);
}
public async Task<bool> DeleteMessageAsync()
{
CheckIfAuthorized();
return Xamarin.Essentials.SecureStorage.Remove(_messageKey);
}
private void CheckIfAuthorized()
{
if(!_authorizationService.IsAuthorized)
throw new UnauthorizedAccessException();
}
}
}

View File

@ -42,7 +42,7 @@ namespace SafeMessageStorage.ViewModels
private async Task Authorize(string code) private async Task Authorize(string code)
{ {
if (await _authorizationService.Authorize(code)) if (await _authorizationService.AuthorizeAsync(code))
AuthorizationSucceeded?.Invoke(this, EventArgs.Empty); AuthorizationSucceeded?.Invoke(this, EventArgs.Empty);
else else
{ {

View File

@ -43,7 +43,7 @@ namespace SafeMessageStorage.ViewModels
} }
else else
{ {
if(await _authorizationService.ChangePassword(null, password)) if(await _authorizationService.ChangePasswordAsync(null, password))
PasswordSetSucceeded?.Invoke(this,EventArgs.Empty); PasswordSetSucceeded?.Invoke(this,EventArgs.Empty);
} }
} }