KeyChainを使ってみた

入力されたパスワードを安全に保存するためにKeyChainを使ってみた。
最初保存したレコードを読み出せず苦労したがAccessible属性を設定することで解決した。この属性は必須なのだろうか。

using MonoTouch.Security;

private string LoadPassword (string userCode)
{
  if (string.IsNullOrWhiteSpace (userCode))
    return "";
  using (SecRecord query = CreateSecRecord(userCode)) {
    SecStatusCode res;
    using (SecRecord rec = SecKeyChain.QueryAsRecord (query, out res)) {
      if (res == SecStatusCode.Success && rec.Generic != null) {
        return NSString.FromData (rec.Generic, NSStringEncoding.ASCIIStringEncoding);
      } else {
        return "";
      }
    }
  }
}

private void SavePassword (string userCode, string password)
{
  if (string.IsNullOrWhiteSpace (userCode))
    return;
  RemovePassword (userCode);
  using (SecRecord newRecord  = CreateSecRecord(userCode)) {
    using (NSData pass = NSData.FromString(password)) {
      newRecord.Generic = pass;
      // ↓この行が無いと保存したレコードを読み取ることが出来なかった。
      newRecord.Accessible = SecAccessible.Always;
      SecKeyChain.Add (newRecord);
    }
  }
}

private void RemovePassword (string userCode)
{
  if (string.IsNullOrWhiteSpace (userCode))
    return;
  using (SecRecord query = CreateSecRecord(userCode)) {
    SecKeyChain.Remove (query);
  }
}

private SecRecord CreateSecRecord (string userCode)
{
  // SecKind.GenericPasswordの時、AccountとServiceの2つでもってレコードがユニークになる
  SecRecord rec = new SecRecord (SecKind.GenericPassword);
  rec.Account = userCode.ToLower ();
  rec.Service = "MyService";
  return rec;
}