تایید محافظت شده اندروید

برای کمک به شما در تأیید قصد کاربران هنگام شروع یک تراکنش حساس، مانند انجام پرداخت، دستگاه‌های پشتیبانی‌شده‌ای که اندروید ۹ (سطح API 28) یا بالاتر را اجرا می‌کنند، به شما امکان می‌دهند از تأیید محافظت‌شده اندروید استفاده کنید. هنگام استفاده از این گردش کار، برنامه شما اعلانی را به کاربر نمایش می‌دهد و از او می‌خواهد که یک عبارت کوتاه را تأیید کند که قصد آنها را برای تکمیل تراکنش حساس مجدداً تأیید می‌کند.

اگر کاربر بیانیه را بپذیرد، برنامه شما می‌تواند از یک کلید از Android Keystore برای امضای پیام نمایش داده شده در کادر محاوره‌ای استفاده کند. این امضا با اطمینان بسیار بالایی نشان می‌دهد که کاربر بیانیه را دیده و با آن موافقت کرده است.

احتیاط: تأییدیه حفاظت‌شده اندروید، کانال اطلاعاتی امنی برای کاربر فراهم نمی‌کند. برنامه شما نمی‌تواند هیچ تضمین محرمانگی فراتر از آنچه پلتفرم اندروید ارائه می‌دهد را بپذیرد. به‌ویژه، از این گردش کار برای نمایش اطلاعات حساسی که معمولاً در دستگاه کاربر نمایش نمی‌دهید، استفاده نکنید.

پس از تأیید پیام توسط کاربر، صحت پیام تضمین می‌شود، اما برنامه شما همچنان باید از رمزگذاری داده در حین انتقال برای محافظت از محرمانگی پیام امضا شده استفاده کند.

برای ارائه پشتیبانی از تأیید کاربر با اطمینان بالا در برنامه خود، مراحل زیر را انجام دهید:

  1. با استفاده از کلاس KeyGenParameterSpec.Builder یک کلید امضای نامتقارن ایجاد کنید . هنگام ایجاد کلید، مقدار true به setUserConfirmationRequired() ارسال کنید. همچنین، setAttestationChallenge() را فراخوانی کنید و یک مقدار چالش مناسب ارائه شده توسط طرف اعتمادکننده را ارسال کنید.

  2. کلید تازه تولید شده و گواهی تأیید کلید خود را نزد طرف معتبر مربوطه ثبت کنید.

  3. جزئیات تراکنش را به سرور خود ارسال کنید و از آن بخواهید یک شیء بزرگ دودویی (BLOB) از داده‌های اضافی تولید و برگرداند. داده‌های اضافی ممکن است شامل داده‌هایی باشد که باید تأیید شوند یا نکات تجزیه، مانند محل رشته اعلان.

    برای پیاده‌سازی امن‌تر، BLOB باید حاوی یک نانس رمزنگاری‌شده باشد تا در برابر حملات تکرار محافظت شود و تراکنش‌ها را از ابهام خارج کند.

  4. شیء ConfirmationCallback را تنظیم کنید که به برنامه شما اطلاع دهد چه زمانی کاربر درخواست نمایش داده شده در کادر محاوره‌ای تأیید را پذیرفته است:

    کاتلین

    class MyConfirmationCallback : ConfirmationCallback() {
    
          override fun onConfirmed(dataThatWasConfirmed: ByteArray?) {
              super.onConfirmed(dataThatWasConfirmed)
              // Sign dataThatWasConfirmed using your generated signing key.
              // By completing this process, you generate a signed statement.
          }
    
          override fun onDismissed() {
              super.onDismissed()
              // Handle case where user declined the prompt in the
              // confirmation dialog.
          }
    
          override fun onCanceled() {
              super.onCanceled()
              // Handle case where your app closed the dialog before the user
              // responded to the prompt.
          }
    
          override fun onError(e: Exception?) {
              super.onError(e)
              // Handle the exception that the callback captured.
          }
      }

    جاوا

    public class MyConfirmationCallback extends ConfirmationCallback {
    
      @Override
      public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) {
          super.onConfirmed(dataThatWasConfirmed);
          // Sign dataThatWasConfirmed using your generated signing key.
          // By completing this process, you generate a signed statement.
      }
    
      @Override
      public void onDismissed() {
          super.onDismissed();
          // Handle case where user declined the prompt in the
          // confirmation dialog.
      }
    
      @Override
      public void onCanceled() {
          super.onCanceled();
          // Handle case where your app closed the dialog before the user
          // responded to the prompt.
      }
    
      @Override
      public void onError(Throwable e) {
          super.onError(e);
          // Handle the exception that the callback captured.
      }
    }

    اگر کاربر کادر محاوره‌ای را تأیید کند، تابع فراخوانی onConfirmed() فراخوانی می‌شود. BLOB dataThatWasConfirmed یک ساختار داده CBOR است که علاوه بر سایر جزئیات، شامل متن اعلانی است که کاربر دیده و همچنین داده‌های اضافی که شما به سازنده ConfirmationPrompt ارسال کرده‌اید. از کلید ایجاد شده قبلی برای امضای BLOB dataThatWasConfirmed استفاده کنید، سپس این BLOB را به همراه امضا و جزئیات تراکنش به طرف اعتمادکننده ارسال کنید.

    برای استفاده کامل از تضمین امنیتی که Android Protected Confirmation ارائه می‌دهد، طرف اعتمادکننده باید پس از دریافت پیام امضا شده، مراحل زیر را انجام دهد:

    1. امضای روی پیام و همچنین زنجیره گواهی تأیید کلید امضا را بررسی کنید.
    2. بررسی کنید که گواهی تأیید، پرچم TRUSTED_CONFIRMATION_REQUIRED را داشته باشد، که نشان می‌دهد کلید امضا نیاز به تأیید کاربر مورد اعتماد دارد. اگر کلید امضا یک کلید RSA است، بررسی کنید که ویژگی PURPOSE_ENCRYPT یا PURPOSE_DECRYPT را نداشته باشد.
    3. extraData را بررسی کنید تا مطمئن شوید که این پیام تأیید متعلق به یک درخواست جدید است و هنوز پردازش نشده است. این مرحله از حملات تکرار جلوگیری می‌کند.
    4. برای کسب اطلاعات در مورد اقدام یا درخواست تأیید شده، promptText تجزیه کنید. به یاد داشته باشید که promptText تنها بخشی از پیامی است که کاربر واقعاً آن را تأیید کرده است. طرف اعتمادکننده هرگز نباید فرض کند که داده‌های تأیید شده موجود در extraData با promptText مطابقت دارند.
  5. برای نمایش خودِ کادر محاوره‌ای، منطقی مشابه آنچه در قطعه کد زیر نشان داده شده است را اضافه کنید:

    کاتلین

    // This data structure varies by app type. This is an example.
      data class ConfirmationPromptData(val sender: String,
              val receiver: String, val amount: String)
    
      val myExtraData: ByteArray = byteArrayOf()
      val myDialogData = ConfirmationPromptData("Ashlyn", "Jordan", "$500")
      val threadReceivingCallback = Executor { runnable -> runnable.run() }
      val callback = MyConfirmationCallback()
    
      val dialog = ConfirmationPrompt.Builder(context)
              .setPromptText("${myDialogData.sender}, send
                              ${myDialogData.amount} to
                              ${myDialogData.receiver}?")
              .setExtraData(myExtraData)
              .build()
      dialog.presentPrompt(threadReceivingCallback, callback)

    جاوا

      // This data structure varies by app type. This is an example.
      class ConfirmationPromptData {
          String sender, receiver, amount;
          ConfirmationPromptData(String sender, String receiver, String amount) {
              this.sender = sender;
              this.receiver = receiver;
              this.amount = amount;
          }
      };
      final int MY_EXTRA_DATA_LENGTH = 100;
      byte[] myExtraData = new byte[MY_EXTRA_DATA_LENGTH];
      ConfirmationPromptData myDialogData = new ConfirmationPromptData("Ashlyn", "Jordan", "$500");
      Executor threadReceivingCallback = Runnable::run;
      MyConfirmationCallback callback = new MyConfirmationCallback();
      ConfirmationPrompt dialog = (new ConfirmationPrompt.Builder(getApplicationContext()))
              .setPromptText("${myDialogData.sender}, send ${myDialogData.amount} to ${myDialogData.receiver}?")
              .setExtraData(myExtraData)
              .build();
      dialog.presentPrompt(threadReceivingCallback, callback);

منابع اضافی

برای اطلاعات بیشتر در مورد تأیید حفاظت‌شده اندروید، به منابع زیر مراجعه کنید.

وبلاگ‌ها