2 minute read

  • apk파일은 jar파일과 호환이 되며 zip파일과도 비슷하다.

  • .java -> .class -> .dex -> apk가 되며 이후 keystore를 통해 private key(앱 서명키)로 서명작업에 들어간다.

  • keystore파일의 각 키에는 앱 서명 인증서의 MD5, SHA-1, SHA-256지문이 포함되어 있다. 또한 앱 서명키는 공개키 인증서(.der또는 .pem파일)를 만들어 내며 여기에는 private key의 소유자를 식별하는 메타데이터가 포함되어 있다. 공개키 인증서는 private key를 보고 소유자인지 식별한다.

  • keystore를 구성하는 각 키는 android studio에서 보통 쉽게 생성할 수 있으나 keytool을 사용하여 직접 만드는 것도 가능하다. 이 때 key algorithm(RSA, DSA, EC)과 signature algorithm(SHA1withDSA…등등) 두가지 알고리즘을 설정해 주어야 한다. key algorithm과 signature algorithm은 서로 호환되어야 하며(key algorithm이 RSA라면 signature algorithm은 SHA256withRSA등 RSA로 끝나는 알고리즘을 사용해야 한다.) 호환 안되게 설정하면 호환이 안된다는 예외가 발생하면서 아예 key가 생성되질 않는다.

  • apk가 서명되면 앱 루트에 META-INF파일이 생성되며 해당 파일에는 MANIFEST.MF, CERT.SF, CERT.RSA(또는 DSA)파일이 포함되어 있다. 이 폴더를 지우면 재서명할 수 있다.
    • MANIFEST.MF : apk를 구성하는 파일들의 이름과, 파일의 내용을 설정된 digest algorithm에 따라 해싱한 섹션들로 구성되어 있다. 사이닝을 실행한 jarsigner에 옵션으로 설정된 digest algorithm에 따라 SHA-1, SHA-256등으로 해싱된다.
    • CERT.RSA : 공개키 인증서이다. 명령어등을 통해 내용을 보면 서명 알고리즘 부분이 서명을 할 때 사용된 key의 서명 알고리즘과 일치한다.
    • CERT.SF : apk를 구성한 파일들과 MANIFEST.MF파일까지를 signature algorithm에 따라 private key를 이용하여 해싱한다. 여기서 signature algorithm은 jarsigner의 -sigalg 옵션에 설정된 대로 결정되며 이 옵션값은 key를 생성할 때의 -sigalg 옵션을 따라야 한다. 이 파일의 해시 값들은 public key로 복호화가 가능하며 앱이 설치될 때 기기의 PackageParser가 앱을 파싱하는 와중에 jarVerifier가 CERT.SF를 public key로 복호화한 후 복호화된 내용을 MANIFEST.MF파일의 해시값과 같은지 비교하여 서명을 확인한다. 그럼 MANIFEST.MF의 파일을 암호화 하면 CERT.SF파일의 내용과 같아야 하지만 이는 확인하지 못했다. 나중에 해 볼 것
  • keytool : JDK에 포함. keystore 생성, 조회 등의 작업
  • keytool 공식문서

// 키스토어 파일 생성 ex keytool -genkey -v -keystore testkey.keystore -alias testkey -keyalg RSA -sigalg SHA256withRSA -keysize 571 -validity 10000

  • private key의 keyalg가 RSA이면 서명 알고리즘은 SHA256withRSA로, DSA이면 SHA256withDSA로, EC이면 SHA256withECDSA로 기본 설정된다.

// 키스토어 파일 상세내역 조회 keytool -list -v -keystore testkey.keystore

// RSA, DSA파일 상세내역 조회 keytool -printcert -v -file /Users/dhkang/Desktop/aosworks/android-img/app/build/outputs/debug/IAMGROUND_1.1.1_10101001_debug_20200710_1303/META-INF/TESTKEY.RSA

// zip파일 수동 서명 jarsigner -keystore testkey.keystore -storepass testkey -keypass testkey -sigalg SHA256withRSA -digestalg SHA-256 /Users/dhkang/Desktop/aosworks/android-img/app/build/outputs/debug/IAMGROUND_1.1.1_10101001_debug_20200710_1303.zip testkey

-keyalg : DSA, RSA, EC, DiffieHellman(?)

-sigalg : NONEwithRSA, MD2withRSA, MD5withRSA, SHA1withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA, NONEwithDSA, SHA1withDSA, NONEwithECDSA, SHA1withECDSA, SHA256withECDSA, SHA384withECDSA, SHA512withECDSA, <digest>with<encryption>

-digestalg : MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512

  • key의 만들 때 -keyalg과 -sigalg은 호환되어야 한다.
  • jarsigner로 사이닝할 때의 -sigalg과 key의 -sigalg은 일치해야 한다.
  • jarsigner로 사이닝할 때의 -digestalg은 key의 key alg이나 sig alg과는 상관이 없는 듯 하다. 어떤 기준이 있는지 확인해 볼 것

  • 안드로이드 스튜디오가 실제로 사이닝 할 때는 명령어를 사용하는지?
  • 공개키 인증서 파일(.der또는 .pem파일)의 내용 실제로 확인해 볼 것
  • signing algorithm이 실제로 뭘 어떻게 사이닝 하는지 인풋 아웃풋을 확인해볼 것
  • 사이닝 scheme v1, v2, v3정리 할 것...뭔가 완전히 다른얘기 같은데?
  • apksigner와 jarsigner는 다른 것인가?

Categories:

Updated: