Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/193.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 存储SqlCipher数据库加密密钥的正确方法_C#_Android_Xamarin_Xamarin.android_Sqlcipher - Fatal编程技术网

C# 存储SqlCipher数据库加密密钥的正确方法

C# 存储SqlCipher数据库加密密钥的正确方法,c#,android,xamarin,xamarin.android,sqlcipher,C#,Android,Xamarin,Xamarin.android,Sqlcipher,我有一个Xamarin应用程序,并设法将数据从服务器下载到设备上。我还将其设置为可以使用SqlCipher加密密钥来加密数据 我的问题是,用于加密此数据的密钥的正确存储位置在哪里?这是你的密钥库/密钥链吗?我应该使用哪些mono类?由于这个问题的流行,我将发布我的实现: PCL接口 public interface IAuth { void CreateStore(); IEnumerable<string> FindAccountsForService(string

我有一个Xamarin应用程序,并设法将数据从服务器下载到设备上。我还将其设置为可以使用SqlCipher加密密钥来加密数据


我的问题是,用于加密此数据的密钥的正确存储位置在哪里?这是你的密钥库/密钥链吗?我应该使用哪些mono类?

由于这个问题的流行,我将发布我的实现:

PCL接口

public interface IAuth
{
    void CreateStore();
    IEnumerable<string> FindAccountsForService(string serviceId);
    void Save(string pin,string serviceId);
    void Delete(string serviceId);
}
公共接口IAuth
{
void CreateStore();
IEnumerable FindAccountsForService(字符串serviceId);
作废保存(字符串pin、字符串serviceId);
作废删除(字符串serviceId);
}
Android

public class IAuthImplementation : IAuth
{
    Context context;
    KeyStore ks;
    KeyStore.PasswordProtection prot;

    static readonly object fileLock = new object();

    const string FileName = "MyProg.Accounts";
    static readonly char[] Password = null;

    public void CreateStore()
    {

        this.context = Android.App.Application.Context;

        ks = KeyStore.GetInstance(KeyStore.DefaultType);

        prot = new KeyStore.PasswordProtection(Password);

        try
        {
            lock (fileLock)
            {
                using (var s = context.OpenFileInput(FileName))
                {
                    ks.Load(s, Password);
                }
            }
        }
        catch (Java.IO.FileNotFoundException)
        {
            //ks.Load (null, Password);
            LoadEmptyKeyStore(Password);
        }
    }

    public IEnumerable<string> FindAccountsForService(string serviceId)
    {
        var r = new List<string>();

        var postfix = "-" + serviceId;

        var aliases = ks.Aliases();
        while (aliases.HasMoreElements)
        {
            var alias = aliases.NextElement().ToString();
            if (alias.EndsWith(postfix))
            {
                var e = ks.GetEntry(alias, prot) as KeyStore.SecretKeyEntry;
                if (e != null)
                {
                    var bytes = e.SecretKey.GetEncoded();
                    var password = System.Text.Encoding.UTF8.GetString(bytes);
                    r.Add(password);
                }
            }
        }
        return r;
    }

    public void Delete(string serviceId)
    {
        var alias = MakeAlias(serviceId);

        ks.DeleteEntry(alias);
        Save();
    }

    public void Save(string pin, string serviceId)
    {
        var alias = MakeAlias(serviceId);

        var secretKey = new SecretAccount(pin);
        var entry = new KeyStore.SecretKeyEntry(secretKey);
        ks.SetEntry(alias, entry, prot);

        Save();
    }

    void Save()
    {
        lock (fileLock)
        {
            using (var s = context.OpenFileOutput(FileName, FileCreationMode.Private))
            {
                ks.Store(s, Password);
            }
        }
    }

    static string MakeAlias(string serviceId)
    {
        return "-" + serviceId;
    }

    class SecretAccount : Java.Lang.Object, ISecretKey
    {
        byte[] bytes;
        public SecretAccount(string password)
        {
            bytes = System.Text.Encoding.UTF8.GetBytes(password);
        }
        public byte[] GetEncoded()
        {
            return bytes;
        }
        public string Algorithm
        {
            get
            {
                return "RAW";
            }
        }
        public string Format
        {
            get
            {
                return "RAW";
            }
        }
    }

    static IntPtr id_load_Ljava_io_InputStream_arrayC;

    void LoadEmptyKeyStore(char[] password)
    {
        if (id_load_Ljava_io_InputStream_arrayC == IntPtr.Zero)
        {
            id_load_Ljava_io_InputStream_arrayC = JNIEnv.GetMethodID(ks.Class.Handle, "load", "(Ljava/io/InputStream;[C)V");
        }
        IntPtr intPtr = IntPtr.Zero;
        IntPtr intPtr2 = JNIEnv.NewArray(password);
        JNIEnv.CallVoidMethod(ks.Handle, id_load_Ljava_io_InputStream_arrayC, new JValue[]
            {
                new JValue (intPtr),
                new JValue (intPtr2)
            });
        JNIEnv.DeleteLocalRef(intPtr);
        if (password != null)
        {
            JNIEnv.CopyArray(intPtr2, password);
            JNIEnv.DeleteLocalRef(intPtr2);
        }
    }
公共类IAuth实现:IAuth
{
语境;
密钥库;
KeyStore.passwordprot;
静态只读对象fileLock=新对象();
常量字符串FileName=“MyProg.Accounts”;
静态只读字符[]密码=null;
public void CreateStore()
{
this.context=Android.App.Application.context;
ks=KeyStore.GetInstance(KeyStore.DefaultType);
prot=新密钥库。密码保护(密码);
尝试
{
锁(文件锁)
{
使用(var s=context.OpenFileInput(文件名))
{
ks.加载(s,密码);
}
}
}
catch(Java.IO.FileNotFoundException)
{
//ks.Load(空,密码);
LoadEmptyKeyStore(密码);
}
}
公共IEnumerable FindAccountsForService(字符串服务ID)
{
var r=新列表();
var postfix=“-”+serviceId;
var alias=ks.alias();
while(别名.HasMoreElements)
{
var alias=alias.NextElement().ToString();
if(别名.EndsWith(后缀))
{
var e=ks.GetEntry(别名,prot)作为KeyStore.SecretKeyEntry;
如果(e!=null)
{
var bytes=e.SecretKey.GetEncoded();
var password=System.Text.Encoding.UTF8.GetString(字节);
r、 添加(密码);
}
}
}
返回r;
}
公共作废删除(字符串serviceId)
{
var alias=MakeAlias(serviceId);
ks.DeleteEntry(别名);
Save();
}
公共作废保存(字符串pin、字符串serviceId)
{
var alias=MakeAlias(serviceId);
var secretKey=新的SecretAccount(pin);
var entry=newkeystore.SecretKeyEntry(secretKey);
ks.SetEntry(别名、条目、保护);
Save();
}
作废保存()
{
锁(文件锁)
{
使用(var s=context.OpenFileOutput(FileName,FileCreationMode.Private))
{
ks.存储(s,密码);
}
}
}
静态字符串MakeAlias(字符串服务ID)
{
返回“-”+serviceId;
}
类SecretAccount:Java.Lang.Object,ISecretKey
{
字节[]字节;
公共秘书帐户(字符串密码)
{
字节=System.Text.Encoding.UTF8.GetBytes(密码);
}
公共字节[]GetEncoded()
{
返回字节;
}
公共字符串算法
{
得到
{
返回“原始”;
}
}
公共字符串格式
{
得到
{
返回“原始”;
}
}
}
静态IntPtr id\u load\u Ljava\u io\u InputStream\u arrayC;
void LoadEmptyKeyStore(字符[]密码)
{
if(id\u load\u Ljava\u io\u InputStream\u arrayC==IntPtr.Zero)
{
id_load_Ljava_io_InputStream_arrayC=JNIEnv.GetMethodID(ks.Class.Handle,“load”,“(Ljava/io/InputStream;[C)V”);
}
IntPtr IntPtr=IntPtr.Zero;
IntPtr intPtr2=JNIEnv.NewArray(密码);
CallVoidMethod(ks.Handle,id\u load\u Ljava\u io\u InputStream\u arrayC,新JValue[]
{
新JValue(intPtr),
新JValue(intPtr2)
});
JNIEnv.DeleteLocalRef(intPtr);
if(密码!=null)
{
CopyArray(intPtr2,密码);
JNIEnv.DeleteLocalRef(intPtr2);
}
}
首先在Android应用程序的主活动中调用Create Store。-这可能会得到改进,通过在Save and Delete中检查ks==null并在true时调用该方法,从接口中删除CreateStrore()

iOS

public class IAuthImplementation : IAuth
{
    public IEnumerable<string> FindAccountsForService(string serviceId)
    {
        var query = new SecRecord(SecKind.GenericPassword);
        query.Service = serviceId;

        SecStatusCode result;
        var records = SecKeyChain.QueryAsRecord(query, 1000, out result);

        return records != null ?
            records.Select(GetAccountFromRecord).ToList() :
            new List<string>();
    }

    public void Save(string pin, string serviceId)
    {
        var statusCode = SecStatusCode.Success;
        var serializedAccount = pin;
        var data = NSData.FromString(serializedAccount, NSStringEncoding.UTF8);

        //
        // Remove any existing record
        //
        var existing = FindAccount(serviceId);

        if (existing != null)
        {
            var query = new SecRecord(SecKind.GenericPassword);
            query.Service = serviceId;

            statusCode = SecKeyChain.Remove(query);
            if (statusCode != SecStatusCode.Success)
            {
                throw new Exception("Could not save account to KeyChain: " + statusCode);
            }
        }

        //
        // Add this record
        //
        var record = new SecRecord(SecKind.GenericPassword);
        record.Service = serviceId;
        record.Generic = data;
        record.Accessible = SecAccessible.WhenUnlocked;

        statusCode = SecKeyChain.Add(record);

        if (statusCode != SecStatusCode.Success)
        {
            throw new Exception("Could not save account to KeyChain: " + statusCode);
        }
    }

    public void Delete(string serviceId)
    {
        var query = new SecRecord(SecKind.GenericPassword);
        query.Service = serviceId;

        var statusCode = SecKeyChain.Remove(query);

        if (statusCode != SecStatusCode.Success)
        {
            throw new Exception("Could not delete account from KeyChain: " + statusCode);
        }
    }

    string GetAccountFromRecord(SecRecord r)
    {
        return NSString.FromData(r.Generic, NSStringEncoding.UTF8);
    }

    string FindAccount(string serviceId)
    {
        var query = new SecRecord(SecKind.GenericPassword);
        query.Service = serviceId;

        SecStatusCode result;
        var record = SecKeyChain.QueryAsRecord(query, out result);

        return record != null ? GetAccountFromRecord(record) : null;
    }

    public void CreateStore()
    {
        throw new NotImplementedException();
    }
}
公共类IAuth实现:IAuth
{
公共IEnumerable FindAccountsForService(字符串服务ID)
{
var query=new SecRecord(SecKind.GenericPassword);
query.Service=serviceId;
SecStatusCode结果;
var records=SecKeyChain.QueryAsRecord(查询,1000,输出结果);
返回记录!=空?
records.Select(GetAccountFromRecord.ToList():
新列表();
}
公共作废保存(字符串pin、字符串serviceId)
{
var statusCode=SecStatusCode.Success;
var计数=引脚;
var data=NSData.FromString(serializedAccount,NSStringEncoding.UTF8);
//
//删除任何现有记录
//
var existing=FindAccount(serviceId);
if(现有!=null)
{
var query=new SecRecord(SecKind.GenericPassword);
query.Service=serviceId;
statusCode=SecKeyChain.Remove(查询);
if(statusCode!=SecStatusCode.Success)
{
抛出新异常(“无法将帐户保存到密钥链:“+statusCode”);
}
}
//
//添加此记录
//
var record=新的SecRecord(SecKind.GenericPassword);
record.Service=serviceId;
记录。通用=
public class IAuthImplementation : IAuth
{
    public IEnumerable<string> FindAccountsForService(string serviceId)
    {
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            string[] auths = store.GetFileNames("MyProg");
            foreach (string path in auths)
            {
                using (var stream = new BinaryReader(new IsolatedStorageFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, store)))
                {
                    int length = stream.ReadInt32();
                    byte[] data = stream.ReadBytes(length);

                    byte[] unprot = ProtectedData.Unprotect(data, null);
                    yield return Encoding.UTF8.GetString(unprot, 0, unprot.Length);
                }
            }
        }
    }

    public void Save(string pin, string serviceId)
    {
        byte[] data = Encoding.UTF8.GetBytes(pin);
        byte[] prot = ProtectedData.Protect(data, null);

        var path = GetAccountPath(serviceId);

        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        using (var stream = new IsolatedStorageFileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, store))
        {
            stream.WriteAsync(BitConverter.GetBytes(prot.Length), 0, sizeof(int)).Wait();
            stream.WriteAsync(prot, 0, prot.Length).Wait();
        }
    }

    public void Delete(string serviceId)
    {
        var path = GetAccountPath(serviceId);
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            store.DeleteFile(path);
        }
    }

    private string GetAccountPath(string serviceId)
    {
        return String.Format("{0}", serviceId);
    }

    public void CreateStore()
    {
        throw new NotImplementedException();
    }
}