90 likes | 105 Views
안드로이드 코드 서명. 허준영 (jyheo@hansung.ac.kr). 안드로이드 앱 패키지. APK = Android App Package 자바의 JAR 를 확장한 형태임 JAR 는 ZIP 압축 파일임 MIME type application/ vnd.android.package -archive APK 를 일반적인 zip 으로 보고 압축을 풀면 AndroidManifest.xml classes.dex lib/ - JNI 통한 네이티브 라이브러리
E N D
안드로이드 코드 서명 허준영(jyheo@hansung.ac.kr)
안드로이드 앱 패키지 • APK = Android App Package • 자바의 JAR를 확장한 형태임 • JAR는 ZIP 압축 파일임 • MIME type • application/vnd.android.package-archive • APK를 일반적인 zip으로 보고 압축을 풀면 • AndroidManifest.xml • classes.dex • lib/ - JNI 통한 네이티브 라이브러리 • resources.arsc – 컴파일된 문자열이나 스타일 리소스 • assets/ - 음악 파일이나 폰트 등 • res/ 애니메이션, 이미지, 메뉴 정의 등 리소스 • META-INF/ - 패키지 manifes와 인증서
코드 서명 • 코드 서명 목적 • 코드 무결성(Integrity) 검증 • 코드 제작자 검증(Authenticity) • 디지털 서명 이용 • SHA로 파일을 Digest하고, 그 Digest를 비대칭 암호화(보통 RSA)의 Private키로 암호화 함 • Public key를 포함한 인증서를 함께 저장해서 나중에 검증하게 함 • 인증서 자체의 유효성 검증은 PKI 등을 이용함 • Secure Hash • 해쉬값을 보고 원래 값을 추정하기 어렵게 만듬 • 원본 값이 다른 경우 해쉬 값도 다를 가능성을 높게 만듬 • 대표적으로 SHA가 있음 • SHA 256 해쉬값을 생성하는 예 • $ openssl sha256 -binary AndroidManifest.xml | openssl base64 • 원래 값을 줄인다고 해서 Digest라는 표현도 사용
자바 코드 서명 • JAR 파일 서명 • META-INF/MANIFEST.MF – 파일 이름과 해당 파일의 SHA값이 저장 Manifest-Version: 1.0 Built-By: Generated-by-ADT Created-By: Android Gradle 3.2.1 Name: AndroidManifest.xml SHA-256-Digest: wJzXnNpsUsH5DFiUvSOI6hj2cj/y2g+Oc8NbWVdk5YA= Name: classes.dex SHA-256-Digest: BWii2EGQqbkFNNs7+8Mv0Cz18kAKg1IcTg7qZ47H/i4= … Openssl을 이용하여 AndroidManifest.xml의 SHA-256을 확인 $ openssl sha256 -binary AndroidManifest.xml | openssl base64 wJzXnNpsUsH5DFiUvSOI6hj2cj/y2g+Oc8NbWVdk5YA=
자바 코드 서명 • META-INF/CERT.SF – MANIFEST.MF에 대한 SHA • MANIFEST.MF 파일 전체와 파일 별 SHA값 부분에 대해 SHA를 저장 Signature-Version: 1.0 Created-By: 1.0 (Android) SHA-256-Digest-Manifest: N2aM/6qBUuaghTC5F0z72CdNC6NE1cxDEqgfNF94kaM= X-Android-APK-Signed: 2 Name: AndroidManifest.xml SHA-256-Digest: q6JIVI6/tkw+vD8Nw1GxmAuvu+/AstdDOaaDsXtqIa8= $ openssl sha256 -binary META-INF/MANIFEST.MF | openssl base64 N2aM/6qBUuaghTC5F0z72CdNC6NE1cxDEqgfNF94kaM= MANIFEST.MF의 일부분 $ echo -en "Name: AndroidManifest.xml\r\nSHA-256-Digest: wJzXnNpsUsH5DFiUvSOI6hj2cj/y2g+Oc8NbWVdk5YA=\r\n\r\n" | openssl sha256 -binary | openssl base64 q6JIVI6/tkw+vD8Nw1GxmAuvu+/AstdDOaaDsXtqIa8=
자바 코드 서명 • META-INF/CERT.RSA • CERT.SF 파일의 SHA-256-Digest-Manifest를 RSA 알고리즘의 private key로 암호화한 결과를 CMS 형식으로 저장한 것 • Public key가 저장되어 있음 • CMS = Cryptographic Message Syntax • 서명 검증하기 • CERT.RSA내의 public key를 이용하여 CERT.RSA에 저장된 Digest를 복호화하고 CERT.SF의 값과 비교하여 검증함 $ jarsigner -verify app-debug.apk jar verified.
자바코드 서명 • 서명하기 $ jarsigner -keystoredebug.keystore -sigalg SHA256withRSA -digestalg SHA1 app-debug.apkandroiddebugkey Enter Passphrase for keystore: android jar signed. Warning: The signer's certificate is self-signed.
안드로이드 코드 서명 • 자바 코드 서명과 매우 유사함 • 안드로이드 코드 서명에서는 CA를 통해 인증서를 받을 필요가 없음 • 보통 자바나 다른 코드서명 인증서는 보통 신뢰 CA(Certificate Authority)를 통해 발급 받아야 함 • 앞의 예에서 self-signed라고 Warning이 발생한 이유 • 안드로이드는 셀프 서명된 인증서 사용이 가능함 • 인증서 유효기간은 무시함 • 구글 play store • 앱 패키지를 play store에 등록하면, play store가 개발자 ID에 해당하는 별도의 키를 발급하여 그 키로 다시 서명을 함
패키지 업데이트 • 안드로이드 앱 패키지 업데이트시 기존 설치된 패키지와 동일한 키로 서명되었는지 검사 • 인증서의 유효 기간 등은 검사하지 않음 • 패키지 이름이 동일하더라도 다른 키로 서명되었다면 설치가 차단됨