美文网首页
apk签名原理

apk签名原理

作者: xuefeng_apple | 来源:发表于2021-04-09 19:13 被阅读0次

    经常使用的总结:

    debug 签名:
    development/tools/make_key media '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key networkstack '/C=CN/ST=BeiJing/L=ChaoYang/O=/OU=xxx/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key platform '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key shared '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key testkey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
    
    user签名:
    development/tools/make_key media '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key networkstack '/C=CN/ST=BeiJing/L=ChaoYang/O=user/OU=Pwe/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key platform '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key shared '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
    development/tools/make_key testkey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
    
    ota:
    ../development/tools/make_key releasekey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=xxx/CN=xxx/emailAddress=cm@xxxx.com'
    
    查看生成的格式文件:
    keytool -printcert -file platform.x509.pem
    
    使用signapk.jar 进行签名:android10:
    java -Djava.library.path="out/host/linux-x86/lib64" -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 old.apk  new.apk
    
    android 11:
    ./soong/host/linux-x86/framework/signapk.jar
    
    如何产生jsk (keystore)文件, 只做了debug 模式发的
    ./keytool-importkeypair -k test.jks -p android -pk8 platform.pk8 -cert platform.x509.pem -alias test
    
    如何查看test.jks 是否正确:
    keytool -list -v -keystore test.jks
     
    Android studio 如何使用:
    signingConfigs {
        releaseConfig {
            keyAlias 'test'
            keyPassword 'android '
            storeFile file('/home/xxx/tools/keystore/test.jks')
            storePassword 'android '
        }
    }
    
    
    
    AndroidManifest.xml的manifest节点中添加
    android:sharedUserId=”android.uid.system”,
    Android.mk中增加  LOCAL_CERTIFICATE := platform 
    
    APK中的META-INF/CERT.RSA
    签名之后如何对RSA 进行查看,签名的信息,在android root目录 
    openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text
    

    本文主要讲解签名的原因,签名怎么保证数据的正确,主要知识点

    • 数据摘要(数据指纹,消息摘要)
    • 签名文件和证书
    • 签名Apk包与没有签名的APK 差异在哪里
    • 如何对apk 进行签名

    1-数据摘要

    就是对一个数据源进行一个算法之后得到一个摘要,也叫作数据指纹,不同的数据源,数据指纹肯定不一样,就和人一样

    消息摘要算法(Message Digest Algorithm)是一种能产生特殊输出格式的算法,其原理是根据一定的运算规则对原始数据进行某种形式的信息提取,被提取出的信息就被称作原始数据的消息摘要。
    著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。

    • 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
    • 原始数据不同,消息摘要不相同
    • 具有不可逆性

    2-签名文件和证书

    消息的发送者来说,先要生成一对公私钥对,将公钥给消息的接收者

    • 提取原始消息提取消息摘要;
    • 私钥加密消息摘要;
      上面就是所原始信息的数字签名。【数字签名=私钥对[原始数据摘要]

    消息的接受者来说,收到了:原始的消息内容+附加数字签名.
    接收者收到内容:原始的消息内容+私钥对[原始数据摘要]

    验证正确需要数据摘要算法+公钥,公钥假设是正确的。
    如何验证:数据摘要算法对内容提取摘要 对比公钥解密签名

    图示验证过程:

    3-如何保证公钥是正确的

    数字证书,一般包含以下一些内容:

    • 证书的发布机构(Issuer)
    • 证书的有效期(Validity)
    • 消息发送方的公钥
    • 证书所有者(Subject)
    • 数字签名所使用的算法
    • 数字签名 --》 数字证书也使用到了数字签名,只不过签名的内容是证书
      公钥签发流程
      上面核心内容就是申请者 提出申请公钥, 公信力机构 使用自己的私钥对申请者的公钥数字签名, 公信力机构的公钥是大家都知道的,因此成功后,申请者的client 端就可以通过公信力机构 获取, 以验证公钥的正确性。
      上面的内容是我在理解HTTPS ,一直想不通的地方,现在终于想通了签发机构是如何发送公钥的。
      其实app 的数字签名与上面的CA 机构的签名还是有点区别的。

    APP 是如何保证签名流程的:
    apk签名其实是对所有源文件单独计算摘要, 然后用私钥加密摘要信息再得到一个加密串, 我们称之为
    APK的签名. 你对源文件的修改都会导致签名的变化. 这个是为了验证apk没有被篡改.

    app的升级和重新安装, 检测的并不是这个apk签名, 而是你的包名+私钥的摘要信息, 签名的keystore文件没有变, 私钥的摘要信息也就不会变了.

    google APP store, 当开发者第一步开发的时候,就需要有自己的签名,私钥的摘要信息上传到goole APP store, 如果升级的时候, 私钥的摘要不一致肯定不能升级app 的上传,这里应该做了校验的。

    4-签名Apk包与没有签名的APK 差异在哪里

    源码位置:com/android/signapk/sign.java
    Android签名apk之后,会有一个META-INF文件夹,这里有三个文件:

    • MANIFEST.MF
    • CERT.RSA
    • CERT.SF

    MANIFEST.MF是:
    逐一遍历里面的所有条目,如果是目录就跳过,如果是一个文件,就用SHA1(或者SHA256)消息摘要算法提取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”属性的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”属性,其值就是该文件在apk包中的路径。

    CERT.SF:
    逐条计算MANIFEST.MF文件中每一个块的SHA1,并经过BASE64编码后,记录在CERT.SF中的同名块中,属性的名字是“SHA1-Digest

    CERT.RSA:
    把之前生成的 CERT.SF文件, 用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入 CERT.RSA 中保存,还有私钥的摘要信息

    5-如何对apk 进行签名

    5.1生成签名文件

    development/tools/make_key testkey  '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
    
    development/tools/make_key platform '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
    

    如何查看生成的platform.X509.pem:
    build/target/product/security/platform.x509.pem
    keytool -printcert -file platform.x509.pem
    或者
    openssl x509 -inform PEM -subject_hash_old -in platform.x509.pem -text

    单独给APP签名方法:
    java -Djava.library.path="out/host/linux-x86/lib64" -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 old.apk new.apk

    APP签名之后,如何查看CERT.RSA 信息
    openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

    6-Android OTA releasekey 替换

    6.1生成key
    系统默认的key如下,首先需要产生以下4种我们项目自己的OTA签名key文件,每一种类型的key都是成对生成的,.509.pem后缀名的是公钥,.pk8后缀名的是私钥。
    testkey -- a generic key for packages that do not otherwise specify a key.
    platform -- a test key for packages that are part of the core platform.
    shared -- a test key for things that are shared in the home/contacts process.
    media -- a test key for packages that are part of the media/download system.

    将XXX替换为自己公司信息。
    生成文件如下:
    media.pk8 media.x509.pem platform.pk8 platform.x509.pem
    releasekey.pk8 releasekey.x509.pem shared.pk8 shared.x509.pem

    将生成的key 文件放到项目相关的目录下,针对Amlogic项目放到device/amlogic/p341/sign_keys。这样我们公司的key就生成了。

    6.2.更改编译规则,使编译过程中使用我们新生成的key对OTA进行签名
    首先在build/core/Makefile里搜索testkey, 查看testkey是怎么用到编译系统的,看到如下编译选项:

     ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
     BUILD_KEYS := test-keys
     else
     BUILD_KEYS := dev-keys
     endif
    

    继续查看DEFAULT_SYSTEM_DEV_CERTIFICATE,可以看到在build/core/config.mk文件里有如下:

     # The default key if not set as LOCAL_CERTIFICATE
     ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
       DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
     else
       DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
     endif
    

    因此要想使用releasekey,只需要指定PRODUCT_DEFAULT_DEV_CERTIFICATE的值即可,因此在device/amlogic/p341/p341.mk中指定项目特定变量
    PRODUCT_DEFAULT_DEV_CERTIFICATE := device/amlogic/p341/sign_keys/releasekey
    同时在根据规则,在build/core/Makefile改动如下:

     ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),device/amlogic/p341/sign_keys/releasekey)
     BUILD_KEYS := release-keys
     endif
    

    6.3. Androoid.mk 使用platform 签名
    对于apk的签名,系统会根据apk里指定的key进行签名。如果系统中的apk的android.mk中没有设置LOCAL_CERTIFICATE的值,就默认使用testkey。

     ifeq ($(LOCAL_CERTIFICATE),)
         LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
     endif
     private_key := $(LOCAL_CERTIFICATE).pk8
     certificate := $(LOCAL_CERTIFICATE).x509.pem
    

    而如果设置成:
    LOCAL_CERTIFICATE := platform
    就代表使用platform来签名,这样的话这个apk就拥有了和system相同的签名
    如何产生jks文件,提供给android studio 开发使用,进行系统签名
    jks文件:
    第一种方式
    https://github.com/chear/keytool-importkeypair
    ./keytool-importkeypair -k test.jks -p android -pk8 platform.pk8 -cert platform.x509.pem -alias test
    最终会生成 test.jks
    -k test.jks: test表示最终生成的jks的名字,可以自定义
    android : 输入当前jks的密码,可以自定义。
    alias test: test表示别名,可以自定义,建议和上面的jks一致。

    第二种方式: 该方式作为记录,实际与第一种方式是想通的,可以看keytool-importkeypair 脚本

    1、编译android源码。
    2、cd build/target/product/security/ 
    3、执行
    openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
    生成platform.pem文件
    
    4、
    openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:123456 -name test
    生成platform.p12文件,其中 "test" 为alias名(app添加签名要用到),"123456" 为密码。
    
    5、执行 
    keytool -importkeystore -deststorepass test -destkeystore platform.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass test
     
    生成platform.jks (app打签名最终用到的文件),
    -deststorepass "123456" 设置的是这个签名的密码,
    -src*     的其他参数都是从前面两个指令中生成的。
     
    6、生成platform.jks
    keytool -importkeystore -srckeystore platform.jks -destkeystore platform.jks -deststoretype pkcs12
    

    说明:platform.jks 实际是含有了公钥与私钥, 这个是不能release给第三方的,只能给自己公司研发使用

    思考:

    • 一个数据内容使用一个签名就可以,一个app 使用一个签名就可以,如果重复签名会怎么样?
      重复使用signapk 签名会覆盖,上次的签名失效,【没有使用studio 多次签名试过,看到有别名的可以有多个】


    • 普通签名与系统签名的区别?
      签名是保证数据不被改写
      系统签名就是要获取一些系统权限,修改时间权限等等
      普通签名仅仅保证数据正确,单存的app 开发,上传到APP store ,不需要获取修改系统的权限。

    • app升级过程中,如何保证升级APP 数据是正确的?
      数字签名 与公钥联合,配合私钥的数据摘要,android 升级过程进行了对比,如果在第一次安装设备时候就修改了数字签名,那么再次安装正确的app 不会成功。 因此老老实实从Apple store 下载,这样保证app 正确,没有打广告等

    • https协议中的公钥,私钥处理方式,ssl 中公钥如何传递给使用者?
      通过CA 公信力结构,公钥分发给使用者,ssl协议在协商过程使用非对称加密技术, 最后协商出对称秘钥进行通信,对称秘要没有在网络上传递, 是双方通过算法计算出来的。

    7 设计原则与测试结果

    7.1设计原则
    签名文件规格:(device.mk设计参考之前的)
    1)Userdebug 与user 区别
    userdebug 系统platform.jks 有可能release 给别人,因此user版本设计成不一样的。
    user 系统platform.jks 仅仅relase公司的app 开发人员
    2)user 与ota ,只是ota 多了releaseky,其他文件都一样

    7.2测试华为手机user version【开发者模式】:

    • debug app 可以正常安装, 在AndroidManifest.xml 添加了 android:sharedUserId="android.uid.system"

    • release apk(没有签名), 不能安装,【 在AndroidManifest.xml 添加了 android:sharedUserId="android.uid.system"

    • release apk(使用platform 签名[android10 google原生platformq签名]), 这种方式可以正常安装

    • release apk(使用platform 签名[自己制作android10platformq签名]), 这种方式可以正常安装
      上面两种都可以安装,在运行的时候对系统权限的多种有所不同。

    • release apk(使用platform 签名[自己制作android10platformq签名]), 这种方式可以正常安装,安装之后再次对APK 签名(使用原生签名文件), 发现CERT.RSA 签名文件失效, 不能再次安装,提示签名不匹配

    Performing Streamed Install
    adb: failed to install C:\Users\Desktop\old.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.example.demo signatures do not match previously installed version; ignoring!]
    

    REF:
    https://www.jianshu.com/p/76e5f5e64b85
    https://developer.android.google.cn/studio/publish/app-signing
    ota relase key 参考

    下载文件地址:
    git clone https://github.com/getfatday/keytool-importkeypair.git

    相关文章

      网友评论

          本文标题:apk签名原理

          本文链接:https://www.haomeiwen.com/subject/lnlwkltx.html