Skip to content

Instantly share code, notes, and snippets.

@trinnguyen
Created September 13, 2020 16:40
Show Gist options
  • Save trinnguyen/0f2f21f0992bb6663eb54adff4ae2995 to your computer and use it in GitHub Desktop.
Save trinnguyen/0f2f21f0992bb6663eb54adff4ae2995 to your computer and use it in GitHub Desktop.
Simple wrapper for iOS Keychain usage for key-value
using Foundation;
using Security;
namespace TnnCrypto
{
public class DefaultKeychain
{
static DefaultKeychain()
{
string id = NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleIdentifier")?.ToString() ?? "";
ServiceId = $"__secured_userdefaults_{id}";
}
private static readonly string ServiceId;
private static SecAccessible DefaultAccessible => SecAccessible.AfterFirstUnlock;
public void SetString(string value, string key)
{
SecRecord newAttr = CreateRecordFromKey(key);
newAttr.ValueData = NSData.FromString(value, NSStringEncoding.UTF8);
// find existing
SecRecord existing = GetRecord(key);
if (existing != null)
{
SecKeyChain.Update(existing, newAttr);
}
else
{
SecKeyChain.Add(newAttr);
}
}
public string GetString(string key)
{
SecRecord existing = GetRecord(key);
var data = existing?.ValueData;
return data != null ? new NSString(data, NSStringEncoding.UTF8) : null;
}
public void Remove(string key)
{
SecKeyChain.Remove(CreateRecordFromKey(key));
}
private static SecRecord GetRecord(string key)
{
SecRecord result = SecKeyChain.QueryAsRecord(CreateRecordFromKey(key), out SecStatusCode status);
if (status == SecStatusCode.Success && result != null)
return result;
return null;
}
private static SecRecord CreateRecordFromKey(string key)
{
return new SecRecord(SecKind.GenericPassword)
{
Account = key,
Service = ServiceId,
Label = key,
Accessible = DefaultAccessible
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment