• Android 理解/生成/使用/查看 签名(V1-V4)


    该文章主要针对于android签名部分进行较为详细的说明,旨在理解签名的整体使用体系及keytool和apksigner的常见用法,重在实践意义。


    1 签名的理解(V1 V2 V3 V4签名)

    在 Android 应用签名中,V1 V2 V3 V4签名是不同的签名方案,具体描述如下:

    • V1 签名(JAR 签名):早期 Android 应用签名的基本形式,基于 Java 签名(JAR 签名)规范。它将应用的整个 APK 文件作为一个整体进行签名,包括应用的所有内容(包括清单文件、资源文件和代码文件等)。V1 签名使用了基于 MD5 和 SHA1 的哈希算法,以及 RSA 或 DSA 加密算法。
    • V2 签名(APK 签名方案 v2+):Android 7.0(API 级别 24)及更高版本引入的新签名方案。它采用了一种增量签名的方法,只对 APK 内容的部分进行签名,而不是整个 APK 文件。这种增量签名可以提供更好的签名效率和验证性能,并且不会破坏 APK 的完整性。V2 签名使用了基于 SHA256 的哈希算法,并采用 ECDSA(椭圆曲线数字签名算法)进行签名。它还提供了对 APK 文件进行验证和完整性检查的机制,以确保 APK 在传输和安装过程中没有被篡改。V2 签名是对 V1 签名的增强,而不是互斥的。在支持 V2 签名的设备上,应用将同时包含 V1 和 V2 两种签名方案,以保证在各种设备上的兼容性和验证方式。V2 签名是在 V1 签名基础上引入的增强方案,提供了更好的效率和安全性。
    • V3 签名(APK 签名方案 v3+): Android 9.0(API 级别 28)及更高版本引入的新签名方案。它是对 V2 签名的进一步增强。V3 签名采用了更强大的签名算法(基于 RSA 或 ECDSA)和更长的密钥长度,以提供更高的安全性。V3 签名与 V2 签名类似,仍然采用增量签名的方式,只对 APK 内容的部分进行签名。V3 签名在验证和完整性检查方面与 V2 签名相似,但它还提供了一些额外的安全特性,例如签名块的完整性保护和签名的附加时间戳。需要注意的是,V3 签名是可选的,应用可以同时包含 V1、V2 和 V3 三种签名方案。V3 签名的引入进一步提升了应用的安全性和验证机制,同时确保了对旧版 Android 设备的兼容性。开发者可以选择在构建应用时使用 V3 签名来提高应用的安全性水平。
    • V4 签名(APK 签名方案 v4+): Android 11.0 引入,用来支持 ADB 增量 APK 安装。v4 签名基于根据 APK 的所有字节计算得出的 Merkle 哈希树。它完全遵循 fs-verity 哈希树的结构(例如,对salt进行零填充,以及对最后一个分块进行零填充。)Android 11 将签名存储在单独的 [apk name].apk.idsig 文件中。v4 签名需要 v2 或 v3 签名作为补充。运行 adb install --incremental 命令时,adb 会要求 .apk.idsig 文件存在于 .apk 旁边。默认情况下,它还会使用 .idsig 文件尝试进行增量安装;如果此文件缺失或无效,该命令会回退到常规安装。

    应用签名 | 对应官方文档链接如下:

    这些官方文档更易于理解应用签名这件事儿。

    2 签名的生成

    2.1 keytool工具简介

    签名的生成主要通过Android Studio/工具keytool使用(普通签名)或者Android Framework生成(主要针对系统签名)。这里的Keytool是Android开发工具包(Android SDK)中的一个工具,用于生成和管理数字证书、密钥对和证书请求。它是一个命令行工具,用于执行与密钥和证书相关的操作,例如创建密钥存储、生成密钥对、导出证书等。

    Android Keytool的一些常见用途和功能如下:

    • 生成密钥对:Android Keytool可以生成公钥和私钥对,这对密钥可以用于加密、解密和数字签名等操作。
    • 创建密钥存储:Keytool可以创建一个密钥存储文件(KeyStore),它是一个加密的容器,用于存储密钥和证书。密钥存储可以是一个单独的文件,也可以是操作系统的密钥库。
    • 管理证书:使用Keytool可以管理数字证书,包括查看证书的详细信息、导出证书、导入证书等。证书通常用于验证数字签名和建立安全连接。
    • 生成证书请求:Keytool可以生成一个证书请求(Certificate Signing Request,CSR),用于向证书颁发机构(Certificate Authority,CA)申请数字证书。CSR包含有关实体(例如应用程序或网站)的信息,以便CA可以验证并颁发相应的证书。
    • 导入和导出密钥对:Keytool允许将密钥对导出到文件,以便在其他系统中使用。它还可以导入其他系统生成的密钥对,以便在Android应用程序中使用。
    • 验证证书链:Keytool可以验证证书链,即由多个证书组成的层次结构。它可以验证证书的有效性、完整性和合法性。

    2.2 keytool常用命令整理

    2.2.1 生成密钥对

    1. $keytool -genkeypair -alias myalias -keyalg RSA -keysize 2048 -keystore keystore.jks
    2. -genkeypair:生成密钥对的命令。
    3. -alias myalias:指定密钥对的别名myalias。
    4. -keyalg RSA:指定密钥算法为RSA算法。
    5. -keysize 2048:指定密钥长度为2048位。
    6. -validity 365 有效期365天,默认90天
    7. -keystore keystore.jks:指定密钥库文件名为keystore.jks。

    2.2.2 导出证书

    1. $keytool -exportcert -alias myalias -keystore keystore.jks -file certificate.crt
    2. -exportcert:导出证书的命令。
    3. -alias myalias:指定要导出的证书的别名。
    4. -keystore keystore.jks:指定密钥库文件名为keystore.jks。
    5. -file certificate.crt:指定导出的证书文件名为certificate.crt。

    2.2.3 导入证书

    1. $keytool -importcert -alias myalias -file certificate.crt -keystore keystore.jks
    2. -importcert:导入证书的命令。
    3. -alias myalias:指定要导入的证书的别名。
    4. -file certificate.crt:指定要导入的证书文件名为certificate.crt。
    5. -keystore keystore.jks:指定密钥库文件名为keystore.jks。

    2.2.4 列出密钥库中的条目

    1. $keytool -list -keystore keystore.jks
    2. -list:列出密钥库中的条目的命令。
    3. -keystore keystore.jks:指定要列出的密钥库文件名为keystore.jks。

    2.2.5 查看证书详细信息

    1. $keytool -printcert -file certificate.crt
    2. -printcert:查看证书详细信息的命令。
    3. -file certificate.crt:指定要查看的证书文件名为certificate.crt。

    2.2.6 查看签名证书详细信息

    使用工具keytool来查看apk签名,使用方法如下:

    $keytool -printcert -jarfile XXX.apk

    如果未签名或者keytool禁用的弱算法签名的,会显示:

    1. $keytool -printcert -jarfile XXX.apk
    2. 不是已签名的 jar 文件

    如果签名的话则会显示:

    1. $keytool -printcert -jarfile XXX.apk
    2. 签名者 #1:
    3. Certificate #1:
    4. 所有者: CN=XXX, OU=XXX, O=XXX, L=xxx, ST=xxx, C=XXX
    5. 发布者: CN=XXX, OU=XXX, O=XXX, L=xxx, ST=xxx, C=XXX
    6. 序列号: 706e325f
    7. 生效时间: Fri Jun 04 13:59:30 CST 2021, 失效时间: Sun May 11 13:59:30 CST 2121
    8. 证书指纹:
    9. SHA1: 67:DC:CE:BD:3E:BB:67:AD:A4:CC:D6:65:B3:1C:2A:33:4F:B0:74:89
    10. SHA256: 92:93:EE:B8:A3:4B:57:3D:32:0E:F7:D2:52:80:4A:74:E0:BB:16:00:11:7E:6E:B4:80:41:6B:FA:E4:6D:D5:EF
    11. 签名算法名称: SHA256withRSA
    12. 主体公共密钥算法: 2048 位 RSA 密钥
    13. 版本: 3
    14. 扩展:
    15. #1: ObjectId: 2.5.29.14 Criticality=false
    16. SubjectKeyIdentifier [
    17. KeyIdentifier [
    18. 0000: 54 0C 4B 25 7D 3D E1 2D 1E 1C 9F 93 BE 1D 39 08 T.K%.=.-......9.
    19. 0010: 14 8E 32 00 ..2.
    20. ]
    21. ]

    注意:这里如果使用高版本的keytool,有可能V1和V2的签名都会显示“不是已签名的 jar 文件”,但是V3会正常显示。

    3 使用工具签名

    3.1 apksigner简介

    apksigner是Android SDK中提供的一个命令行工具,用于对Android应用程序(APK)进行数字签名。它是为了确保APK在发布和安装过程中的完整性和安全性而设计的。

    apksigner的一些主要特点和功能如下:

    • 数字签名:apksigner使用开发者的私钥对APK进行数字签名。数字签名是一种安全机制,用于验证APK的来源和完整性。签名后的APK可以防止未经授权的修改和篡改,并提供了一种信任机制,使用户能够验证APK的真实性。
    • 支持多种签名方案:apksigner支持使用不同的签名方案对APK进行签名,包括旧版JAR签名(JAR Signature Scheme v1)和现代APK签名方案(APK Signature Scheme v2+)。后者是Android 7.0及更高版本的推荐签名方案,它提供更好的安全性和验证能力。
    • 验证签名:apksigner可以验证已签名的APK的签名信息,包括签名方案、证书链、证书指纹等。这样可以确保APK在发布和传输过程中没有被篡改,并且可以验证APK的来源。
    • 自动优化:apksigner能够自动优化APK,以减小APK的大小并提高运行性能。它可以删除未使用的资源、压缩文件和优化dex文件等,从而减少APK的体积。
    • 兼容性:apksigner与Android系统兼容,并且与Google Play Store的要求一致。在将APK上传到Google Play Store进行发布时,apksigner是必需的,因为Google Play要求APK必须进行数字签名。
    • 自动/手动构建:作为构建工具的一部分自动执行,也可以手动运行以对现有的APK进行签名和验证。

    3.2 签名常用命令

    使用apksigner工具进行V1 V2 V3 V4签名。apksigner.jar/apksigner工具是Android自带的工具中的命令,放在Sdk/build-tools/$版本号/目录下。

    早期apksigner的版本是jar包,使用apksigner.jar文件和xxx.jks来给应用签名,具体操作如下:

    $java -jar apksigner.jar sign --ks xxx.jks --ks-key-alias xxx1 --ks-pass pass:xxx2  --key-pass pass:xxx3 --out [签名后生成的文件/out输出参数] [需要签名的文件/in输入参数]

    后来改为apksigner可执行文件,具体操作如下:

    $apksigner sign --ks xxx.jks --ks-key-alias xxx1 --ks-pass pass:xxx2  --key-pass pass:xxx3 --out [签名后生成的文件/out输出参数] [需要签名的文件/in输入参数]

    3.3 apksigner关键参数解读(sign和verify子命令)

    3.3.1 sign参数的详细解读

    如果需要重新签名/更换签名,直接更换jks文件即可。这里涉及的参数说明如下:

    1. --ks xxx.jks 密钥库名
    2. --ks-key-alias xxx1 密钥别名,若密钥库有一个密钥对,则可省略,反之必选
    3. --ks-pass pass:xxx2 解锁密钥库文件的密码
    4. --key-pass pass:xxx3 解锁私钥的密码

    对于签名的 还可以设置签名版本解决方案,如下所示:

    1. --v1-signing-enabled 是否开启V1签名,默认开启
    2. --v2-signing-enabled 是否开启V2签名,默认开启
    3. --v3-signing-enabled 是否开启V3签名,默认开启
    4. --v4-signing-enabled 是否开启V4签名,默认开启

    关于sign的其他命令,可以使用 apksigner sign --help来查看。

    3.3.2 verify参数的详细解读

    常用参数说明如下:

    1. -v 输出签名的模式V1/V2/V3/V4的值未true/false
    2. --print-certs 打印签名详细信息

    具体使用如下:

    1. #这里的输出表示V2签名
    2. $apksigner verify -v xxx1.apk
    3. Verifies
    4. Verified using v1 scheme (JAR signing): false
    5. Verified using v2 scheme (APK Signature Scheme v2): true
    6. Verified using v3 scheme (APK Signature Scheme v3): false
    7. Number of signers: 1
    8. #这里输出的表示V1+V2+V3签名
    9. $apksigner verify -v xxx1.apk
    10. Verifies
    11. Verified using v1 scheme (JAR signing): true
    12. Verified using v2 scheme (APK Signature Scheme v2): true
    13. Verified using v3 scheme (APK Signature Scheme v3): true
    14. Number of signers: 3
    15. #这里打印cert的详细信息
    16. apksigner verify --print-certs xxx.apk
    17. Signer #1 certificate DN: CN=xxx1, OU=xxx2, O=xxx3, L=xxx, ST=xxx, C=xxx
    18. Signer #1 certificate SHA-256 digest: 6793eeb8a34b573d320ef7d25208a474e0bb1600117e6e4b80416bfae46dd5fe
    19. Signer #1 certificate SHA-1 digest: 24dc9cbd3ebb67ada4bdd665b31c2a994fb07444
    20. Signer #1 certificate MD5 digest: 1252800c8673bd059951fcaf66a5b91c
    21. #同时使用参数-v和--print-certs,打印更全面的信息
    22. $apksigner verify -v --print-certs xxx.apk
    23. Verifies
    24. Verified using v1 scheme (JAR signing): false
    25. Verified using v2 scheme (APK Signature Scheme v2): false
    26. Verified using v3 scheme (APK Signature Scheme v3): true
    27. Number of signers: 1
    28. Signer #1 certificate DN: CN=xxx1, OU=xxx2, O=xxx3, L=xxx4, ST=xxx5, C=xxx6
    29. Signer #1 certificate SHA-256 digest: 6793eeb8a34b573d320ef7d25208a474e0bb1600117e6e4b80416bfae46dd5fe
    30. Signer #1 certificate SHA-1 digest: 24dc9cbd3ebb67ada4bdd665b31c2a994fb07444
    31. Signer #1 certificate MD5 digest: 1252800c8673bd059951fcaf66a5b91c
    32. Signer #1 key algorithm: RSA
    33. Signer #1 key size (bits): 2048
    34. Signer #1 public key SHA-256 digest: 39e722630a16ebbc200a1cac68b2ac6689ae9f56bff911c229ef2a81f5c24b5c
    35. Signer #1 public key SHA-1 digest: 5b9b6707d59e3aee0f844830cc3cc7074499fe2f
    36. Signer #1 public key MD5 digest: 36cdbb8876ef2ffc59dcafeb59f26810

    关于verify的其他命令,可以使用 apksigner verify --help来查看。

  • 相关阅读:
    GreenPlum DB向GBase迁移_TIME类型
    Java内部类 (详细讲述java内部类)
    关于技术面试一些有用的经历
    数据类型(面向对象)
    网站建设中的视觉设计:吸引和保留用户
    composer切换全局镜像源的方法
    Revit如何使用幕墙功能绘制百叶窗
    使用DiskGenius拓展系统盘C盘的容量
    Linux软件管理
    一文搞懂C++临时对象优化 附详细样例
  • 原文地址:https://blog.csdn.net/vviccc/article/details/134076285