EZLippi-浮生志

Android APK签名详解

App为什么需要签名?

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

1
2
3
4
5
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中输入:

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

命令行参数解释:

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

使用 jarsigner签名

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

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

命令行参数解释:

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

zipalign压缩对齐优化APK文件

1
zipalign -v 4 android_signed.apk release.apk

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

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

使用Gradle完成签名

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 命令,

1
$ gradle assembleRelease

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

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

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

1
2
3
4
5
6
7
8
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,具体的就不介绍了,看了前面的部分应该很简单完成。

🐶 您的支持将鼓励我继续创作 🐶

热评文章