본문 바로가기
android

[무결성 검증] 앱 서명키 비교

by liz_devel 2024. 10. 11.

무결성 검증이 무엇이냐?

앱이 실행되는 시점에 내가 개발한 앱이 변경되었는지 위, 변조 여부를 탐지하는 기능이다.

 


 

무결성 검증 방법은 다양하게 있다.

 

이중에서 앱 서명키 비교하는 방법을 포스팅해보려고 한다.

 

일단 앱 서명키를 비교하려면 준비물로 내가 앱을 빌드할 당시 사용했던 서명키의 정보와 현재 실행하는 앱의 서명키가 필요하다.

 

 

내가 앱을 배포하기 위해 사용했던 서명키의 정보를 어떻게 알 수 있지?

일단 서명키를 만들어뒀던 가정하에 내 서명키.jks파일이 어디 있는지 확인한다.

그리고 밑에 명령어를 터미널에 입력해준다.

* <> 새로 입력해야 될 부분을 표시하였다. 입력 시에는 <>를 제거해줘야 한다.

keytool -list -v -keystore <내 키 경로> -alias <내 키 이름>

 

위 명령어를 입력하니 비밀번호를 입력하라고 뜨는데 무슨 비밀번호를 입력하라는 거야?

 

키 생성 당시 storePassword와 keyPassword를 입력하였을 것이다.

그중 storePassword를 입력해주면 된다.

 

비밀번호를 올바르게 입력할 경우 다음과 같이 키 정보들이 뜬다.

 

 

 

SHA1, SHA256 두 개가 뜨는데 뭘 써야 하지?

SHA-1과 SHA-256은 모두 SHA(Secure Hash Algorithm) 시리즈에 속하는 해시 함수다.

특성 SHA-1 SHA-256
해시 길이 160비트 (20바이트) 256비트 (32바이트)
보안성 안전하지 않은 것으로 간주됨 (충돌 가능) 더 높은 보안성 (충돌 저항력 강함)
처리 속도 일반적으로 빠름 SHA-1보다 느림 (하지만 현대 하드웨어에서는 큰 차이 없음)
사용 용도 과거에 많이 사용되었지만 현재는 권장하지 않음 보안 프로토콜, 블록체인, 디지털 서명 등에서 널리 사용됨

 

안전하지 않고 권장하지 않는데 SHA-1은 왜 여전히 제공돼?

SHA-1은 현재 보안성이 부족하지만, 과거의 레거시 시스템과 호환성을 유지하기 위해 여전히 제공되고 있다. 그러나 새로운 시스템에서는 SHA-256 또는 그 이상의 보안 알고리즘을 사용하는 것이 권장된다. 이를 통해 보안성을 높이고 향후 발생할 수 있는 위험을 줄일 수 있기 때문이다.

 

 

SHA-256 해시키를 build.gradle에 넣어준다.

buildConfigField "String", "EXPECTED_SIGNATURE", "\"여기에 넣어줍니다\""

*보안성을 위해 해시키는 그대로 넣는 것보다 local.properties에 넣고 properties 변수를 넣어주는 것을 추천한다.

 

앱 해시 비교 함수

fun checkAppHash(): Boolean {
        val packageName = context.packageName

        return try {
            // 패키지 정보 획득
            val packageInfo: PackageInfo = context.packageManager.getPackageInfo(
                packageName,
                PackageManager.GET_SIGNING_CERTIFICATES
            )

            // 서명 정보 획득
            val signatures = packageInfo.signingInfo.apkContentsSigners

            // 서명의 SHA-256 해시값 계산
            val certBytes = signatures[0].toByteArray()
            val digest = MessageDigest.getInstance("SHA-256")
            val publicKey = digest.digest(certBytes)

            // 해시를 문자열로 변환
            val hashString = publicKey.joinToString(":") { String.format("%02X", it) }

            // 해시 비교
            if (hashString == BuildConfig.EXPECTED_SIGNATURE) {
                // 서명 검증 완료
                true
            } else {
                // 서명 검증 실패
                false
            }
        } catch (e: Exception) {
            false
        }
    }

 

반응형