LoginSignup
6
7

More than 5 years have passed since last update.

Touch ID: プライベートキーをTouch IDプロテクトする

Last updated at Posted at 2014-09-25

アプリのマスターキーをJwkSetで管理したい

SecKind.GenericPassword で保存する

  • どうも SecKind.Key だと うまく行かない

        const SecKind KIND =  SecKind.GenericPassword;
        public static readonly string SERVICE_NAME = "Auth.Touch";

マスターキーが存在したら削除する

  • KeyChain Itemのクエリレコード

        static readonly SecRecord KEYCHAIN_QUERY = new SecRecord (KIND) {   
            Service = SERVICE_NAME,
            UseOperationPrompt = "Authenticate yourself.",
        };
  • 指定したKeyChain Itemを削除する

        public override void Delete ()
        {
            Evaluate (SecKeyChain.Remove (KEYCHAIN_QUERY));
        }
  • Success以外だと例外を出す

        public static void Evaluate(SecStatusCode  code){
            if (code != SecStatusCode.Success) {
                throw new KeyChainException (code);
            }       
        }

JOSE JwkSetをシリアライズして入れてみる

  • JwkSet をシリアライズして、 SecRecordの Genericにぶち込む
  • コメントにあるようにTouch IDで守りたいのであれば、SecAccessControll を設定する
  • AccessControlを指定しないと、Touch IDのプロンプトでません

        public static SecRecord ToKeyChainItem (
            Jose.JwkSet jwkset, 
            SecAccessControl grant)
        {
            // if AccessControl is not specified,
            // this security record is not protected by TouchID 

            return new SecRecord (KIND) {
                Service = SERVICE_NAME,
                Generic =  NSData.FromString(jwkset.ToJson()),
                UseNoAuthenticationUI = true,
                AccessControl=grant,
            };          
        }
  • Touch ID 用のAccess Controlは以下で渡す事にします

        static readonly SecAccessControl GRANT = new SecAccessControl (
                                                     SecAccessible.WhenPasscodeSetThisDeviceOnly,
                                                     SecAccessControlCreateFlags.UserPresence);

  • 作成。Deleteの例外はItemNotFoundの場合、無視する。

        public override Jose.JwkSet Create ()
        {
            try{
                this.Delete ();
            }catch(KeyChainException ex) {
                if (ex.Code != SecStatusCode.ItemNotFound)
                    throw ex;
            }
            return this.Add (CreateJwkSet());
        }
  • Add

        public Jose.JwkSet Add(Jose.JwkSet jwkset)
        {
            var kci = ToKeyChainItem(jwkset, GRANT);
            Evaluate (SecKeyChain.Add (kci));

            return jwkset;
        }
  • JwkSetはEC521で

        public static Jose.JwkSet CreateJwkSet()
        {
            var jwk = Jose.Jwa.KeyDef.EC.GenerateKey (Jose.Jwa.Ec.CurveEnum.P_521);
            jwk.kid = DateTime.Now.ToString (); // for TEST

            return new Jose.JwkSet () {
                keys = new System.Collections.Generic.List<Jose.Jwk>{ jwk }
            };
        }

参照する

  • Deleteを同じKeyChain Itemをレコードして探す
  • みつかったらJwkSetに復元する

        public override Jose.JwkSet Load ()
        {
            SecStatusCode code;                

            SecRecord resultData = SecKeyChain.QueryAsRecord (
                KEYCHAIN_QUERY, out code);
            Evaluate(code);
            return ToJwkSet(resultData.Generic);
        }

動かす

  • 起動

image

  • 空で削除すると例外

image

  • 新規作成  & 保存

image

  • Browse すると Touch ID 認証

image

  • 認証が通ると表示

image

  • ちなみに“Enter Passcord”でパスコード認証も通ります

image

SecKind.Keyだとうまく行かない

  • Touch ID を使わないと以下のコードで SecKind.Keyで保存できるが、 Touch IDプロテクトすると Param エラー


            SecStatusCode code = SecKeyChain.Add ( new SecRecord ( SecKind.Key ) {
                Service = _service_name,
                Label = _service_name,
                Account = _account_name,
                Generic = NSData.FromString ( jwkset.ToJson(), NSStringEncoding.UTF8 ),
                Accessible = accessible,
                Synchronizable = sync
            } );
  • どのParamでエラーなのかがよくわからん
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7