I am using Windows 10 & Visual Studio 2015 for development and targeting Android, iOS, Windows Phone, Windows Universal.
I wanted to use XLabs SecureStorage Service.
I am using XLabs.Platform package 2.3.0-pre02.
at this line i am getting exception (only for UWP)
secureStorage.Store(key, Encoding.UTF8.GetBytes(value));
And Exception Details are :
FileName : System.Runtime.WindowsRuntime, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
HResult : -2146234304
HelpLink : null
InnerException : null
Message : Could not load file or assembly 'System.Runtime.WindowsRuntime, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Source : XLabs.Platform.UWP
SourceTrack : at XLabs.Platform.Services.SecureStorage.d__6.MoveNext()
at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.StartTStateMachine
at XLabs.Platform.Services.SecureStorage.Store(String key, Byte[] dataBytes)
at UWPTest.SecureStorageService.Store(String key, String value, Boolean overwrite)
After some trial and error i am able to run SecureStorage service successfully on Xamarin UWP.
SecureStorage.cs(Code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ABC.UWP.Common
{
using System;
using System.IO;
using Windows.Storage;
using System.Threading;
using System.Runtime.InteropServices.WindowsRuntime;
using XLabs.Platform.Services;
using Windows.Security.Cryptography.DataProtection;
/// <summary>
/// Implements <see cref="ISecureStorage"/> for WP using <see cref="IsolatedStorageFile"/> and <see cref="ProtectedData"/>.
/// </summary>
public class SecureStorage : ISecureStorage
{
private static Windows.Storage.ApplicationData AppStorage { get { return ApplicationData.Current; } }
private static Windows.Security.Cryptography.DataProtection.DataProtectionProvider _dataProtectionProvider = new DataProtectionProvider();
private readonly byte[] _optionalEntropy;
/// <summary>
/// Initializes a new instance of <see cref="SecureStorage"/>.
/// </summary>
/// <param name="optionalEntropy">Optional password for additional entropy to make encyption more complex.</param>
public SecureStorage(byte[] optionalEntropy)
{
this._optionalEntropy = optionalEntropy;
}
/// <summary>
/// Initializes a new instance of <see cref="SecureStorage"/>.
/// </summary>
public SecureStorage() : this(null)
{
}
#region ISecureStorage Members
/// <summary>
/// Stores the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="dataBytes">The data bytes.</param>
public async void Store(string key, byte[] dataBytes)
{
//var mutex = new Mutex(false, key);
using (var mutex = new Mutex(false, key))
{
try
{
mutex.WaitOne();
var buffer = dataBytes.AsBuffer();
if (_optionalEntropy != null)
{
buffer = await _dataProtectionProvider.ProtectAsync(buffer);
}
var file = await AppStorage.LocalFolder.CreateFileAsync(key, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBufferAsync(file, buffer);
}
catch (Exception ex)
{
throw new Exception(string.Format("No entry found for key {0}.", key), ex);
}
}
//finally
//{
// mutex.ReleaseMutex();
//}
}
/// <summary>
/// Retrieves the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>System.Byte[].</returns>
/// <exception cref="System.Exception"></exception>
public byte[] Retrieve(string key)
{
var mutex = new Mutex(false, key);
try
{
mutex.WaitOne();
return Task.Run(async () =>
{
var file = await AppStorage.LocalFolder.GetFileAsync(key);
var buffer = await FileIO.ReadBufferAsync(file);
if (_optionalEntropy != null)
{
buffer = _dataProtectionProvider.UnprotectAsync(buffer).GetResults();
}
return buffer.ToArray();
}).Result;
}
catch (Exception ex)
{
throw new Exception(string.Format("No entry found for key {0}.", key), ex);
}
finally
{
mutex.ReleaseMutex();
}
}
/// <summary>
/// Deletes the specified key.
/// </summary>
/// <param name="key">The key.</param>
public void Delete(string key)
{
var mutex = new Mutex(false, key);
try
{
mutex.WaitOne();
Task.Run(async () =>
{
var file = await AppStorage.LocalFolder.GetFileAsync(key);
await file.DeleteAsync();
});
}
finally
{
mutex.ReleaseMutex();
}
}
/// <summary>
/// Checks if the storage contains a key.
/// </summary>
/// <param name="key">The key to search.</param>
/// <returns>True if the storage has the key, otherwise false. </returns>
public bool Contains(string key)
{
try
{
return Task.Run(async() => await AppStorage.LocalFolder.GetFileAsync(key)).Result.IsAvailable;
}
catch
{
return false;
}
}
#endregion
}
}