Android应用程序的代码混淆和签名

时间:2023-02-21 21:30:03

动代码混淆功能

在较新版本的Android tools和ADT,项目工程里面是带有proguard.cfg的代码混淆配置文件,但默认是没有启动这个配置的,需要手动地在default.properties里面添加指定这个配置文件:# Project target.target=android-3proguard.config=proguard.cfg然后按F5刷新当前项目工程,这时候Eclipse检测了文件的变动而重新编译!

生成签名发布apk

以下图片转自http://jojol-zhou.iteye.com/blog/719428
1.Eclipse工程中右键工程,弹出选项中选择 android工具-生成签名应用包:Android应用程序的代码混淆和签名
2.选择需要打包的android项目工程(注:这里会自动选择当前的Project的):Android应用程序的代码混淆和签名
3.如果已有私钥文件,选择私钥文件 输入密码,如果没有私钥文件见 第6和7步创建私钥文件:Android应用程序的代码混淆和签名
4.输入私钥别名和密码:Android应用程序的代码混淆和签名
5.选择APK存储的位置,并完成设置 开始生成:Android应用程序的代码混淆和签名
6.没有私钥文件的情况,创建私钥文件(注:这里私钥文件的Location位置最好自己选择一个新位置,便于牢记,而且最好把这个私钥文件备份到其他地方去以免丢失,因为应用程序的更新需要同一私钥文件):Android应用程序的代码混淆和签名
7.输入私钥文件所需信息,并创建(注:这里的密码是用于Key的别名的,和上面的KeyStore文件的不同,这点可以看步骤3和4。另外下面的名字,开发者资料等是不需要全部填写的,dialog会有提示的):Android应用程序的代码混淆和签名
这时候生成的apk,我发现是比debug版本的要小!如果你发现没有变小的话,请确认项目工程是重新编译的!但代码混淆的效果一般般,基本上还是可以看到原来的语句!

1    Eclipse中,选择Android Tools->Export Unsigned Application Package... , 
     接下来,系统会提示你输入apk文件的保存地址。这样我们就编译生成了发布版的未签名的apk文件. eg.sdialer.apk

2    完成了发布版的编译,接下来是获取私钥,会用到JDK下的两种工具:keytool和jarsigner. keytool是生成私钥的工具。

keytool命令的解释:
-genkey                                                           产生一个密钥对(公钥和私钥)
-v                                                                      开启详细输出
-keystore<keystore-name>.keystore         包含私钥的keystore名称
-storepass<password>                                 keystore的密码。安全起见,通常建议不要在命令行输入这个选项,如果你不提供这个选项,
                                                                          keytool就会提示你输入密码,这样你的密码就不会保存在shell历史中。
-alias<alias_name>                                     密钥的别名
-keyalg<alg>                                                 产生密钥的加密算法,可以采用DSA和RSA中的一种
-dname                                                           用于描述密钥的产生者。这个值将作为自签名证书中的发布者。如果你此时没有输入,那么在执行签名时,
                                                                         jarsigner会提示你输入 dname(distinguished  name)
-validity                                                           密钥的有效期,这里以天来计算。我们通常建议大于10000天
-keypass<password>                                  密钥的密码,安全起见,通常建议不要在命令行输入这个选项,如果你不提供这个选项,
                                                                         keytool就会提示你输入密码,这样你的密码就不会保存在shell历史中。


jarsigner命令解释:
-keystore                                                       包含私钥的keystore
<keystore-name>.keystore
-verbose                                                        开启详细输出
-storepass<password>                                keystore的密码,安全起见,通常建议不要在命令行输入这个选项,
                                                                         如果你不提供这个选项,jarsigner就会提示你输入密码,这样你的密码就不会保存在shell历史中。
-keypass<password>                                  密钥的密码,安全起见,通常建议不要在命令行输入这个选项,如果你不提供这个选项,
                                                                         jarsigner就会提示你输入密码,这样你的密码就不会保存在shell历史中。

eg.
keytool -genkey -v -keystore s-dialer.keystore -alias sdialer_name -keyalg RSA -validity 10000

输出一个s-dialer.keystore,密钥别名为sdialer_name。有了密钥,我们就可以用它来进行签名。

签名工具是jarsigner.

eg. jarsigner -verbose -keystore s-dialer.keystore sdialer.apk sdialer_name

这样,就为应用程序sdialer.apk完成了签名


应用程序的版本
Android应用程序主要通过androidmanifest.xml中的android:versionCode和android:versionName来实现版本管理的


应用程序签名

所有 Android 应用程序都必须被签名。应用程序或代码签名是一个这样的过程,即使用私有密钥数字地签署一个给定的应用程序,以便:

识别代码的作者

检测应用程序是否发生了改变

在应用程序之间建立信任

基于这一信任关系,应用程序可以安全地共享代码和数据。

使用相同数字签名签署的两个应用程序可以相互授予权限来访问基于签名的 API,如果它们共享用户 ID,那么也可以运行在同一进程中,从而允许访问对方的代码和数据。

应用程序签名首先是生成一个私有、公共密钥对和一个相关公共密钥证书,简称为公共密钥证书。

构建 Android 应用程序时可以采用调试模式和发布模式:

使用 Android 构建工具(命令行和 Eclipse ADT)构建的应用程序是用一个调试私有密钥自动签名的;这些应用程序被称为调试模式应用程序。调试模式应用程序用于测试,不能够发布。注意,未签名的或者使用调试私有密钥签名的应用程序不能够通过 Android Market 发布。

您准备发布自己的应用程序时,必须构建一个发布模式的版本,这意味着用私有密钥签署应用程序。

Android 中的代码签名采用一种比其他移动平台中要简单得多的方式。在 Android 上,证书可以是自签名的,这就是说,无需证书授权。这种方法简化了发布过程和相关的成本。

接下来,介绍如何从命令行以及通过使用 Eclipse ADT 手动签署 Android 应用程序。本文中不介绍第三种方法,即使用 Ant。

手动创建私有、公共密钥和公共密钥证书

回想一下,调试模式应用程序是使用调试密钥/证书由构建工具自动签名的。要签署一个发布模式的应用程序,首先必须生成私有、公共密钥对和公共密钥证书。可以手动地或者通过使用 Eclipse ADT 签署应用程序。两种方法中都使用了 Java Developer Kit (JDK) keytool 密钥和证书管理实用工具。

要手动生成私有、公共密钥信息,可以从命令行使用 keytool,如 清单 1 所示。

清单 1. 使用 keytool 生成私有/公共密钥和证书

   
   
  1. keytool -genkey -v -alias -keystore 
  2.  
  3. -keyalg RSA -keysize 2048 -validity  

注意:清单 1 假设 JDK 已安装在您的计算机上,并且 JAVA_HOME 路径被正确定义为指向您的 JDK 目录(参见 参考资料,获得下载和设置信息)。

在 清单 1 中,-genkey 表示一个公共、私有密钥对项,以及一个 X.509 v1 自签署的单个元素证书链,其中包含生成的公共密钥。-v表示冗长模式。-alias 是用于 keystore 项的别名,keystore 存储生成的私有密钥和证书。-keystore 表示使用的密钥仓库的名称。-keyalg 是用来生成密钥对的算法。-keysize 是生成的密钥大小,其中默认大小是 1024,但是推荐大小是 2048。-validity 是有效天数;推荐采用大于 1000 的值。

注意:生成密钥之后,一定要保证密钥的安全。不要共享私有密钥,也不要在命令行或脚本中指定密钥;注意,keytool 和 jarsigner 会提示输入密码。关于这一技巧和其他技巧,请参考 Android Developers 网站的 “Securing Your Private Key”(参见 参考资料 中的链接)。

Keytool 提示您输入名和姓、公司、城市、州、国家,从这些信息生成一个 X.500 Distinguished Name(更多信息请参见 参考资料),还要输入保护私有密钥和密钥仓库本身的密码。

对于有效期,请确保使用超出应用程序本身和相关应用程序预期生命期的时期。如果您是在 Android Market 上发布应用程序,那么有效期必须晚于 2033 年 10 月 22 日结束;否则不能上载。此外,拥有长寿命的证书让升级应用程序更为容易。幸运的是,Android Market 强制采用长寿命的证书,以帮助您避免此类问题。

手动签署应用程序

接下来,使用 jarsigner 工具(它是 JDK 的一部分)签署未签名的应用程序:

   
   
  1. jarsigner -verbose -keystore  

在上述代码中,-verbose 表示冗长模式,-keystore 表示使用的密钥仓库的名称。接下来是应用程序的名称 (.apk),最后是用于私有密钥的别名。

Jarsigner 提示您输入使用密钥仓库和私有密钥时的密码。

应用程序可以使用不同的密钥进行多次签名,用相同私有密钥签名的应用程序之间可以建立一种信任关系,并且可以运行在同一进程中,共享代码和数据。

手动优化应用程序

签署过程的最后一步是优化应用程序,以便数据边界与文件的开始是内存对齐的,这种技术有助于改善运行时性能和内存利用率。要签署应用程序,可以使用 zipalign:

   
   
  1. zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk 

在前面的代码中,-v 表示冗长输出。数字 4 表示使用四字节对齐(总是使用四字节)。下一个参数是输入已签署应用程序的文件名 (.apk),它必须用您的私有密钥签署。最后一个参数是输出文件名;如果覆盖现有应用程序,则添加一个 -f。

手动验证应用程序已经签署

要验证应用程序已经签署,可以使用 Jarsigner,这次传递 -verify 标志:

   
   
  1. jarsigner -verify -verbose -certs my_application.apk 

在前面的代码中,-verify 表示验证应用程序;-verbose 表示冗长模式;-certs 表示展示创建密钥的 CN 字段,最后一个参数是要验证的 Android 应用程序包的名称。

注意:如果 CN 读入 "Android Debug",那么意味着应用程序是用调试密钥签署的,这表明不能发布;如果您计划在 Android Market 上发布您的应用程序,一定要记得使用私有密钥。

刚才学习了如何手动创建私有、公共密钥,以及签署和优化应用程序。接下来,了解如何使用 Eclipse ADT 自动创建私有、公共密钥,以及签署和优化应用程序。

使用 Eclipse ADT 创建密钥和证书,以及签署和优化应用程序

要使用 Eclipse ADT 生成密钥,必须导出应用程序。有两种方法从 Eclipse 导出应用程序:

导出您必须手动签署的应用程序的未签署 版本

导出应用程序的已签署 版本,其中所有步骤都由 ADT 为您代劳

导出未签署的应用程序

您可以导出您必须手动签署的应用程序的未签署版本。就是说,您需要手动运行 keytool(如前所述,是为了生成密钥)和 Jarsigner(为了签署应用程序),并使用 zipalign 工具优化应用程序,跟前面解释的那样。

要使用 ADT 导出应用程序的未签署版本,可以右键单击项目并选择 Android Tools>Export Unsigned Application Package(参见图 4)。

图 4. 导出未签署的应用程序

Android应用程序的代码混淆和签名

选中之后,ADT 提示您选择将未签署应用程序导出到的目录。记住,一旦应用程序被导出,您就必须手动签署和优化应用程序,跟前面介绍的那样。

导出已签署的应用程序

利用 Eclipse ADT,您可以导出应用程序的已签署版本。使用这种方法,ADT 提示您输入以下内容:

使用现有 KeyStore 或者创建新的受保护 KeyStore 所需的信息

创建受保护私有密钥所需的信息

生成公共密钥证书所需的信息

要导出已签署的应用程序,可以右键单击项目,但是这一次选择菜单项 Android Tools->Export Signed Application Package,如图 5 所示。

图 5. 导出已签署的应用程序

Android应用程序的代码混淆和签名

此时,Export Wizard 执行,如 图 6 所示。

图 6. Export Wizard

Android应用程序的代码混淆和签名

在 图 7 中,选择一个现有的密钥仓库(或者创建一个新的)和证书。

图 7. Export Wizard:密钥仓库选择

Android应用程序的代码混淆和签名

在 图 8 中,输入信息以创建私有密钥和数字证书。

图 8. Export Wizard:创建私有密钥和数字证书

Android应用程序的代码混淆和签名

在 图 9 中,输入目标文件的路径和名称,并验证有效期间。

图 9. 输入目标文件的路径和名称

Android应用程序的代码混淆和签名

完成时,您就有了一个发布模式的已签署和已优化的应用程序,您可以发布它。

另外,您也可以使用 Android Manifest 工具调用 Export Wizard,如 图 10 所示。

图 10. 使用 Android Manifest 工具调用 Export Wizard

Android应用程序的代码混淆和签名

应用程序签署之后,下一步由您在 manifest 中定义应用程序需要的权限。接下来将描述这一过程。

注意,Android Developer 网站有非常好的关于应用程序签署的文档