Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

Android 보안 확인

Android 9(API 수준 28) 이상을 실행하는 지원되는 기기는 Android 보안 확인을 사용할 수 있는 기능을 제공합니다. 이 워크플로를 사용할 때, 사용자에게 짧은 문을 승인해 달라고 요구하는 메시지가 앱에 표시됩니다. 앱에서는 이 문을 통해 사용자가 결제와 같은 중요한 트랜잭션을 완료하겠다는 의사를 재차 확인할 수 있습니다.

사용자가 이 문을 수락하면 앱에서는 Android Keystore의 키를 사용하여 대화상자에 표시된 메시지에 서명할 수 있습니다. 이 서명은 강한 확신을 가지고 사용자가 문을 보고 그 내용에 동의했음을 나타냅니다.

주의: Android 보안 확인은 사용자를 위한 보안 정보 채널을 제공하지 않습니다. 앱은 Android 플랫폼이 제공하는 수준을 넘어서는 그 어떤 기밀성을 보장할 책임을 질 수 없습니다. 특히, 통상적으로 사용자 기기에 표시하지 않을 민감한 정보를 표시하려는 목적으로 이 워크플로를 사용해서는 안 됩니다.

사용자가 메시지를 확인하면 메시지의 무결성이 보증되지만, 그래도 앱은 전송 중 데이터 암호화를 사용하여 서명된 메시지의 기밀성을 보장해야 합니다.

앱에서 높은 수준의 사용자 확인 지원을 제공하려면 다음 단계를 완료하세요.

  1. KeyGenParameterSpec.Builder 클래스를 사용하여 비대칭 서명 키를 생성합니다. 키를 생성할 때 truesetUserConfirmationRequired()로 전달합니다. 또한, setAttestationChallenge()를 호출하여 신뢰 당사자가 제공하는 적절한 챌린지 값을 전달합니다.

  2. 적절한 신뢰 당사자에 새로 생성된 키와 키의 증명 인증서를 등록합니다.

  3. 트랜잭션 세부 정보를 서버로 전송하여 서버에서 추가 데이터의 blob을 생성 및 반환하도록 합니다. 추가 데이터에는 확인해야 할 데이터나 파싱 힌트(예: 메시지 문자열의 언어)가 포함될 수 있습니다.

    좀 더 안전하게 구현하려면 재생 공격으로부터 보호하고 트랜잭션의 모호성을 없애기 위해 암호화 nonce를 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
                // could respond to the prompt.
            }
    
            override fun onError(e: Exception?) {
                super.onError(e)
                // Handle the exception that the callback captured.
            }
        }
        

    사용자가 대화상자를 승인하면 onConfirmed() 콜백이 호출됩니다. dataThatWasConfirmed blob은 다른 세부정보 중에서도 특히 사용자가 확인한 메시지 텍스트와 개발자가 ConfirmationPrompt 빌더로 전달한 추가 데이터가 포함되어 있는 CBOR 데이터 구조입니다. 앱은 이전에 만든 키를 사용하여 dataThatWasConfirmed blob에 서명해야 합니다. 그런 다음, 개발자는 서명 및 트랜잭션 세부정보와 함께 이 blob도 신뢰 당사자에게 다시 전달해야 합니다.

    Android 보안 확인에서 제공하는 보안 보증을 최대한 활용하려면 신뢰 당사자는 서명된 메시지를 받으면 다음 단계를 수행해야 합니다.

    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 just 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)
        

참고 자료

Android 보안 확인에 대한 자세한 내용은 다음 리소스를 참조하세요.

블로그