Android APK签名详解

458次阅读  |  发布于5年以前

App为什么需要签名?

  1. 对Apk的完整性和发布机构唯一性的校验
  2. 签名之后无法阻止APK被人修改,但修改后再签名就和原先的签名不一致,可以避免有些人用相同包名的APK来替换已有的应用
  3. 相同签名的升级软件可以覆盖安装旧版本的软件
  4. 签名的私钥在开发者那里,公钥打包在APK内,不同公钥对应不同私钥,通过比较公钥可以判断私钥是否一致
  5. 允许代码和数据共享。android中提供了一个基于签名的Permission标签。通过允许的设置,我们可以实现对不同App之间的访问和共享,如下:
AndroidManifest.xml:<permission android:protectionLevel="normal" />  

其中protectionLevel标签有4种值:normal(缺省值),dangerous, signature,signatureOrSystem。normal是低风险的,所有的App不能访问和共享此App。dangerous是高风险的,所有的App都能访问和共享此App。signature是指具有相同签名的App可以访问和共享此App。

使用SDK工具生成的DEBUG Key签名

Android签名有两种方式:DEBUG和RELEASE,在开发测试期间使用DEBUG方式,BUILD时,会自动使用工具KeyTools创建KEY包括别名和密码。每次编译时,都会使用DEBUG的KEY进行签名。
在第一次安装Android开发环境的时候,SDK工具已经创建了缺省的keystore/key和账号、密码:

Keystore name - "debug.keystore"  
    Keystore password - "android"  
    Key alias - "androiddebugkey"  
    Key password - "android"  
    CN - "CN=Android Debug,O=Android,C=US"  

keystore其实就是一个文件,存放以上信息的文件,由于使用了加密难以看懂。DEBUG模式的签名只有365天有效期,过了有效期,编译会出错。但不用担心,只要将debug.keystore文件删除后,下次BUILD会自动生成的keystore和key的。debug.keystore文件一般在/home/username/.android目录下。

使用java命令行工具

使用Keytool生成key文件

创建key,需要用到keytool(位于JAVA_HOME\jre\bin目录下),在Shell中输入:

keytool -genkey -alias android.keystore -keyalg RSA -validity 36500 -keystore android.keystore  

命令行参数解释:

-genkey:产生秘钥  
    -alias android.keystore 别名 android.keystore  
    -keyalg RSA 使用RSA算法对签名加密  
    -validity 36500 有效期限  
    -keystore android.keystore  存储的文件名  

使用 jarsigner签名

jarsigner在目录JAVA_HOME\bin下,在Shell中输入:

jarsigner -verbose -keystore android.keystore -signedjar android_signed.apk android.apk android.keystore  

命令行参数解释:

-verbose 输出签名的详细信息  
    -keystore  android.keystore 密钥库位置  
    -signedjar android_signed.apk android.apk android.keystore 正式签名,三个参数中依次为签名后产生的文件android_signed,要签名的文件android.apk和密钥库android.keystore  

zipalign压缩对齐优化APK文件

zipalign -v 4 android_signed.apk release.apk  

zipalign能够使apk文件中未压缩的数据在4个字节边界上对齐,这样android系统可以使用mmap()函数读取文件,在读取资源上获得较高的性能。

android系统中的Davlik虚拟机使用自己专有的格式DEX,DEX的结构是紧凑的,为了让运行时的性能更好,可以进一步用"对齐"进一步优化,但是大小一般会有所增加。

使用Gradle完成签名

前面已经介绍了DEBUG模式的签名,这里主要讲Release模式:
在Module的build.gradle文件的android配置代码块添加如下内容:

android{  
        signingConfigs {  
            debug {  
                storeFile file("/home/lippi/.android/debug.keystore")  
            }  
            relealse {  
                //这样写就得把demo.jk文件放在项目目录  
                storeFile file("android.keystore")  
                storePassword "android"  
                keyAlias "lippi"  
                keyPassword "password"  
            }  
        }  
       buildTypes {  
            debug {  
                // 显示Log  
                buildConfigField "boolean", "LOG_DEBUG", "true"  

                versionNameSuffix "-debug"  
                minifyEnabled false  
                zipAlignEnabled false  
                shrinkResources false  
                signingConfig signingConfigs.debug  
            }  

            release {  
                // 不显示Log  
                buildConfigField "boolean", "LOG_DEBUG", "false"  
                //混淆  
                minifyEnabled true  
                //Zipalign优化  
                zipAlignEnabled true  

                // 移除无用的resource文件  
                shrinkResources true  
                //前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明  
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'  
                //签名  
                signingConfig signingConfigs.relealse  
            }  
        }  
    }  

执行gradle 命令,

$ gradle assembleRelease  

编译并发布。 在build/outputs/apk/ 下能看到未签名的apk 和 已经签名的apk。如果未用签名文件,使用debug mode的debug签名,那就会生成一个debug签名的apk。

签名密码放在Gradle文件中不安全

可以改成下面这样的格式这样在执行命令时,就会被要求输入密码

signingConfigs {   
        myConfig {   
            storeFile file("android.keystore")    
            storePassword System.console().readLine("\ninput Keystore password: ")    
            keyAlias "lippi"    
            keyPassword System.console().readLine("\n input Key password: ")    
        }   
    }  

使用Android Studio自带的签名工具

菜单Build > Generate Signed APK,具体的就不介绍了,看了前面的部分应该很简单完成。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8