Bitwarden-app-android-iphon.../src/Android/Services/KeyStoreStorageService.cs

112 lines
2.9 KiB
C#

using System.IO;
using System.IO.IsolatedStorage;
using Java.Lang;
using Java.Security;
using Javax.Crypto;
using Android.OS;
using Bit.App.Abstractions;
namespace Bit.Android.Services
{
public class KeyStoreStorageService : ISecureStorageService
{
private const string StorageFile = "Bit.Android.KeyStoreStorageService";
private static readonly object SaveLock = new object();
private readonly KeyStore _keyStore;
private readonly KeyStore.PasswordProtection _protection;
public KeyStoreStorageService()
: this(Build.Serial.ToCharArray()) { }
public KeyStoreStorageService(char[] password)
{
_keyStore = KeyStore.GetInstance(KeyStore.DefaultType);
_protection = new KeyStore.PasswordProtection(password);
if(File.FileExists(StorageFile))
{
using(var stream = new IsolatedStorageFileStream(StorageFile, FileMode.Open, FileAccess.Read, File))
{
_keyStore.Load(stream, password);
}
}
else
{
_keyStore.Load(null, password);
}
}
private static IsolatedStorageFile File
{
get { return IsolatedStorageFile.GetUserStoreForApplication(); }
}
public void Store(string key, byte[] dataBytes)
{
_keyStore.SetEntry(key, new KeyStore.SecretKeyEntry(new SecureData(dataBytes)), _protection);
Save();
}
public byte[] Retrieve(string key)
{
var entry = _keyStore.GetEntry(key, _protection) as KeyStore.SecretKeyEntry;
if(entry == null)
{
return null;
}
return entry.SecretKey.GetEncoded();
}
public void Delete(string key)
{
_keyStore.DeleteEntry(key);
Save();
}
public bool Contains(string key)
{
return _keyStore.ContainsAlias(key);
}
private void Save()
{
lock(SaveLock)
{
using(var stream = new IsolatedStorageFileStream(StorageFile, FileMode.OpenOrCreate, FileAccess.Write, File))
{
_keyStore.Store(stream, _protection.GetPassword());
}
}
}
private class SecureData : Object, ISecretKey
{
private const string Raw = "RAW";
private readonly byte[] _data;
public SecureData(byte[] dataBytes)
{
_data = dataBytes;
}
public string Algorithm
{
get { return Raw; }
}
public string Format
{
get { return Raw; }
}
public byte[] GetEncoded()
{
return _data;
}
}
}
}