Google Play Integrity API를 활용하여 앱무결성 검증하기

강현석·2024년 4월 27일
0

performance

목록 보기
3/3
post-thumbnail

앱무결성 검증 로직 살펴보기


1. Integrity API를 통해 Integrity Token 과 Access Token 발급을 요청한다.
2. Play 서버에 Integrity Token과 Access Token을 전달하여 복호화 및 검증을 요청한다.
3. 검증을 통과했다면 JSON 형태의 Response를 전달한다.

연동하기

1. 라이브러리 추가

  • com.google.android.play:integrity:x.y.z
    • Integrity Token 생성 시 필요하다.
  • com.google.auth:google-auth-library-oauth2-http:x.y.z
    • Access Token 생성 시 필요하다.
  • com.squareup.retrofit2:retrofit:x.y.z
    • Token 복호화 및 검증 시 필요하다.

2. Play Integrity API 활성화하기

  1. Google Play Console에 들어갑니다.
  2. "앱 무결성"의 "Play Integrity API" 항목에 "설정" 버튼을 누릅니다.
  3. "Cloud 프로젝트 연결" 버튼을 클릭하여 Google Cloud Platform(이하 GCP)에서 프로젝트를 생성한 후 연결합니다.

3. Integrity Token 생성하기

Standard Request 방식으로 Integrity API를 사용해서 Integrity Token을 생성합니다.

withContext(Dispatchers.IO) {
    standardIntegrityManager.prepareIntegrityToken(
        StandardIntegrityManager.PrepareIntegrityTokenRequest
            .builder()
            .setCloudProjectNumber(CLOUD_PROJECT_NUMBER)
            .build()
    )
        .await()
        .request(
            StandardIntegrityTokenRequest.builder()
                .setRequestHash(requestHash)
                .build()
        )
        .await()
        .token()
}
  • CLOUD_PROJECT_NUMBER
    • GCP에 등록된 프로젝트 번호를 의미한다.
  • requestHash
    • 앱서명키와 같이 식별할 수 있는 값을 넣으시면 됩니다.

4. Access Token 생성하기

Google에서 제공하는 API를 사용하려면 Access Token을 생성해야 합니다.

withContext(Dispatchers.IO) {
    gcpInputStream.use {
        val credentials = GoogleCredentials.fromStream(it)
            .createScoped(listOf(INTEGRITY_SCOPE))

        credentials.refreshIfExpired()

        (credentials as? ServiceAccountCredentials)?.accessToken
            ?.tokenValue
            .orEmpty()
    }
}
  • gcpInputStream
    • GCP 서비스 계정의 Key에 대한 정보입니다.
    • Key는 JSON 형식의 파일로 구성되어 있으며, 이 것을 InputStream으로 만든 것입니다.
  • INTEGRITY_SCOPE
    • Integrity API URL 정보입니다.
    • https://www.googleapis.com/auth/playintegrity
  • 서비스 계정의 Key 발급 방법
    1. GCP에서 "IAM 및 관리자"로 이동합니다.
    2. "서비스 계정" 메뉴를 누릅니다.
    3. "키" 탭을 누른 후 "키 추가" > "새 키 만들기" 를 누릅니다.
    4. "JSON" 형식의 키로 생성합니다.

5. Token 복호화 및 검증하기

Google API를 활용하여 Token을 복호화 및 검증합니다.

@POST("v1/${패키지명}:decodeIntegrityToken")
suspend fun decodeToken(
    @Header("Authorization") accessToken: String,
    @Body request: IntegrityRequest
): IntegrityResponse

@Serializable
data class IntegrityRequest(
    @SerialName("integrity_token")
    val token: String
)

integrityAPI.decodeToken(
    accessToken = "Bearer $accessToken",
    request = IntegrityRequest(token = integrityToken)
)
  • 패키지명에는 앱의 패키지명을 기입합니다.
    • 예) v1/com.beok.runewords:decodeIntegrityToken

6. 앱무결성 체크하기

  • 전달한 requestHash(앱서명키 등)가 유효한지 확인합니다.
if (response.tokenPayloadExternal.requestDetails.requestHash != requestHash)
  • Response의 requestHash와 Integrity Token 생성 시 전달한 reqeustHash가 일치하는지 확인합니다.
  • 다르다면 앱 무결성이 깨졌다고 판단합니다.
  • 아래 3가지 유형으로 전달됩니다.
    • PLAY_RECOGNIZED
    • UNRECOGNIZED_VERSION
    • UNEVALUATED

주의사항

  • 기존에 생성한 Key를 활용하지 않고 반드시 새로 키를 생성하셔야 합니다.
    • 기존에 생성한 Key에는 Google Play Integrity API가 활성화된 정보가 담겨있지 않기 때문입니다.
    • 이 것 때문에 삽질한 시간이...
  • Google Integrity API는 request limit이 존재합니다. (하루 10,000회)
  • Google Play가 설치되어있지 않거나 활성화되어있지 않다면, 앱무결성이 깨진 것으로 판단합니다.

참고

profile
볼링을 좋아하는 안드로이드 개발자

5개의 댓글

comment-user-thumbnail
2024년 8월 13일

play integrity api 관련 찾고있는 와중에 포스팅 정말 유용하게 봤습니다! 혹시 실례가 안된다면 코드 전문을 볼 수 있는 곳이 있을까요?

2개의 답글
comment-user-thumbnail
2024년 12월 13일

안녕하세요! 좋은 글 감사합니다. 앱 단에서 모두 인증 api 요청한 건지 궁금합니다. :)

1개의 답글