概述

Android系统要求,所有的程序经过数字签名后才能安装。Android系统使用这个证书来识别应用程序的作者,并且建立程序间的信任关系。证书不是用于用户控制哪些程序可以安装。证书不需要授权中心来签名:Android应用程序上使用自己签名的证书是完全允许且普遍的。

理解Android应用程序签名有以下几个重要点:

·所有的应用程序都必须签名。系统不会安装任何一个不签名的程序。

·你可以使用自己的证书来签名。不需要任何授权中心。

·当你要为最终用户发布你的应用程序的时候,你必须签入一个合适的密钥。你不可以发布程序的时候还使用SDK工具签入的Debug Key

·系统只在安装应用程序的时候检测证书的有效期。如果应用程序在安装之后证书失效了,那么,应用程序还是可以正常工作。

·你可以使用标准工具——KeytoolJarsigner——生成Key并签名apk文件。

·一旦你为应用程序签名了,一定要使用zipalign工具来优化最终的APK包。

Android系统不会安装和运行没有正确签名的应用程序。这条规则适用于任何运行Android系统的地方,不管是真机还是模拟器。正是由于这个原因,你必须在模拟器或真机上运行/调试程序之前对程序进行签名。

当你调试应用程序时,Android SDK工具替你对应用程序进行了签名。EclipseADT插件和Ant编译工具都提供了两种签名模式——Debug模式和Release模式。

·当开发和测试时,你可以使用Debug模式。在Debug模式下,编译工具使用内嵌在JDK中的Keytool工具来创建一个keystore和一个key(包含公认的名字和密码)。在每次编译的时候,使用这个Debug Key来为apk文件签名。由于密码是公认的,在每次编译的时候,也不需要提示你输入keystorekey密码。

·当你的程序准备发布时,你必须在Release模式下,使用密钥来为apk文件签名。有以下两种方式可以做到:

o命令行中使用KeytoolJarsigner。在这个方法中,首先需要编译出一个未签名的apk。然后使用Jarsigner(或相似的工具),用你的密钥为apk手动签名。如果你没有合适的密钥,你可以运行Keytool来手动生成自己的keystore/key

o使用ADT导出向导。如果你使用Eclipse/ADT插件进行开发,你可以使用导出向导来编译程序,生成密钥(如果需要),并为apk签名,所有这些操作都在导出向导中。一旦你的程序签名了,别忘了运行zipalign来为apk进行额外的优化。

签名策略

应用程序签名的某些方面可能会影响应用程序的开发,特别是你打算一起发布多个应用程序的时候。

一般来说,推荐的策略是在整个应用程序寿命内,所有的程序签上相同的证书。以下有几个应该这么做的原因:

·应用程序升级——当你对应用程序进行升级时,如果你想用户平稳的升级,那么,你就需要签上相同的证书。当系统安装一个升级应用程序时,如果新版本的证书与老版本的证书有匹配的话,那么,系统才会允许进行升级。如果你没有为版本签上合适的证书,当你安装时,你需要给应用程序指定一个新的包名——在这种情况下,用户安装的新版本,被当作是一个全新的应用程序。

·应用程序模块化——如果应用程序请求的话,Android系统允许签有相同证书的应用程序运行在相同的进程里,这样,系统就会把它们看作是一个单一的应用程序。用这种方法配置应用程序,用户可以选择更新每个独立的模块。

·代码/数据权限共享——Android系统提供了基于签名的权限检查,因此,如果应用程序间签有特定的证书,那么,它们之间可以共享功能。通过多个程序签有相同的证书并且使用基于签名的权限检查,你的程序可以以一种安全的方式共享代码和数据。

还有一个决定签名策略的重要因素是:如何设定key的有效期。

·如果你计划支持单个应用程序的升级,你需要确保你的key拥有一个超过期望的应用程序生命周期的有效期。推荐使用25年或更多的有效期。当你的key过期了,用户也就不能平稳的更新到新版本了。

·如果你想给多个无关的应用程序签上相同的key,那么,你必须确保key的有效期超过所有应用程序所有版本的生命周期,包括将来有可能添加到这一阵营的程序。

·如果你想在Android Market上发布你的程序,key的有效期必须在2033.10.22以后。Market服务器强制这一要求,目前是保证用户可以平稳的更新他们的程序。

当你设计应用程序时,一定要把这些点记在脑子里,并且使用一个合适的证书来为应用程序签名。

签名的基本设定

在你开始之前,你必须保证KeytoolSDK编译工具来说是可利用的。多数情况下,你可以通过设置JAVA_HOME环境变量来告诉SDK编译工具如何找到Keytool。另外,你还可以添加JDKKeytool的路径到PATH的变量里。

如果你在Linux上开发,并且使用GNU编译器来编译Java,那么,请确保系统是使用JDK中的Keytool,而不是gcj。如果Keytool已经在你的PATH中,它有可能是对/usr/bin/keytool的符号链接。在这种情况下,检查符号链接的目标,确保它是指向JDK中的Keytool

如果你打算对公众释放你的应用程序,你还需要Jarsigner工具。JarsignerKeytool都包含在JDK中。

Debug模式下签名

Android编译工具提供了Debug签名模式,使得开发和调试应用程序更加容易,而且还满足Android系统的签名要求。当使用Debug模式编译你的app时,SDK工具会调用Keytool工具自动创建一个Debugkeystorekey。然后,这个Debug key会自动用于apk的签名,这样,你不需要使用你自己的key来为应用程序包签名。

SDK工具使用预先定义好的名字/密码来创建Debug keystore/key

·Keystore名字:“debug.keysotre

·Keystore密码:“android

·Key别名:“androiddebugkey

·Key密码:“android

·CN:“CN=Android Debug,O=Android,C=US

如果需要的话,你可以改变Debug keystore/key的位置和名字,或者提供一个自定义的Debug keysotre/key。然而,任何自定义的Debug keystore/key必须使用和默认Debug key(上面描述的)相同的名字和密码。(在Eclipse/ADT中,操作Windows>Preferences>Android>Build实现。)

注意:你不能将签有Debug证书的应用程序发布给公众。

Eclipse用户

如果你在Eclipse/ADT下开发(并且已经按照上面描述的“签名的基本设定”配置了Keytool),Debug模式下签名默认是开启的。当你运行或是调试应用程序时,ADT会使用Debug证书进行签名,并运行zipalign,然后安装到选择的模拟器或是连接上的设备。整个过程不需要你参与,前提是ADT能访问Keytool

Ant用户

如果你使用Ant来编译你的apk文件,需要在ant命令中添加debug选项来开启Debug签名模式(假设你正在使用由android工具生成build.xml文件)。当你运行ant debug来编译你的程序时,编译脚本会生成一个keystore/key,并为apk进行签名。然后脚本会使用zipalign工具对apk进行对齐处理。整个过程不需要你参与。阅读“其它IDE下开发:Debug模式编译”来了解更多的信息。

Debug证书过期

Debug模式下签名用的证书(默认是Eclipse/ADTAnt编译)自从它创建之日起,1年后就会失效。

当证书失效时,你会得到一个编译错误,在Ant编译上,错误如下:

debug:[echo] Packaging bin/samples-debug.apk, and signing it with a debug key...[exec] Debug Certificate expired on 8/4/08 3:43 PM

Eclipse/ADT中,Android控制台上你将会看到一个相似的错误。

为了解决这个问题,只需要删掉debug.keystore文件即可。AVD默认存储的位置在:~/.android/avdOS XLinux),C:\Documents and Settings\\.android\Windows XP),C:\Users\\.android\Windows Vista)。

当下一次编译的时候,编译工具会重新生成一个新的keystoreDebug key

Release模式下签名

当你的程序准备好释放给其它用户时,你必须:

1.获取一个合适的密钥

2.Release模式下编译程序

3.使用密钥签名程序

4.对齐APK包

如果你是使用Eclipse/ADT插件开发,你可以使用导出向导来完成编译、签名和对齐等操作。在整个过程中,导出向导甚至还可以生成一个新的keystore和密钥。因此,如果你使用Eclipse,你可以直接跳到“使用Eclipse ADT编译和签名”。

1.获取一个合适的密钥

为了进行程序的签名,首先,你必须有一个合适的密钥。密钥指:

·个人持有。

·代表个人、公司或组织实体的身份。

·拥有一个有效期。有效期推荐超过25年。

如果你在Android Market上发布你的程序,需要注意一点的是:程序的有效期需要在2033.10.22之后。你不能上传一个应用程序,而它的key的有效期是在这个日期之前。

·不是由Android SDK工具生成的Debug key

如果你没有一个合适的key,你一定要使用Keytool来生成一个。如“基本设定”中描述的,确保Keytool可用。

为了用Keytool生成一个key,使用keytool命令并传入一些可选参数,如下表所示。

警告:确保密钥的安全。一定要阅读“安全储存你的密钥”中讨论如何确保你的密钥的安全以及这对你和用户为何如此重要。尤其是,当你生成你的密钥时,一定要为keystorekey使用强密码。

Keytool选项

描述

-genkey

生成一个键对(公钥和密钥)

-v

日志输出

-keystore<keystore-name>.keystore

命名包含密钥的keystore

-storepass <password>

设定keystore的密码。

基于安全考虑,不要在命令行中包含这一选项,除非你在一个安全的计算机上。如果你不提供,Keytool会提示你输入。这样,你的密码就不会储存在shell记录中了。

-alias <alias_name>

设定key的别名

-keyalg <alg>

指定生成key时使用的加密算法。支持DSARSA

-dname <name>

指定一个描述谁创建key的名字。该值将填入证书发行人的字段。

注意:你不需要在命令行中指明这些选项。如果不提供,Jarsigner会提示你输入每个字段(CNOU等)。

-validity <valdays>

Key的有效期,天数。

注意:推荐使用10000或更大的数。

-keypass <password>

Key的密码。

基于安全考虑,不要在命令行中包含这一选项,除非你在一个安全的计算机上。如果你不提供,Keytool会提示你输入。这样,你的密码就不会储存在shell记录中了。

下面是使用Keytool命令生成密钥的例子:

$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -validity 10000

运行上面的例子命令,Keytool会提示你输入keystorekey的密码,并且会提示你输入key中其它的字段。然后,它会生成一个叫做my-release-key.keystore的文件。keystorekey受你输入的密码保护。keystore中包含一个key,有效期为10000天。别名将在后面用到,在程序签名时指当前这个keystore

了解更多关于Keytool的信息,请参考http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security

2.Release模式下编译程序

为了给用户释放程序,你必须在Release模式下编译程序。在Release模式下,编译程序不会进行默认签名,并且你需要使用密钥进行签名。

注意:你不能释放未签名的程序,或签有Debug key的程序。

使用Eclipse

右击Package Explorer中的工程,选择Android Tools>Export Unsigned Application Package,导出一个未签名的apk。然后指定未签名apk的存储位置。(另外,你也可以在Eclipse中打开AndroidManifest.xml文件,打开Manifest Tab,然后点击Export an unsigned APK)。

注意:你也可以使用导出向导来完成编译和签名步骤,参考“使用Eclipse/ADT编译和签名”。

使用Ant

如果你正在使用Ant,那么你可以在ant命令中加入release选项来开启Release模式。例如,如果你在包含build.xml文件的文件夹上运行Ant,命令可能看起来是这样:

ant release

一般,编译脚本在编译apk的时候不会进行签名。输出的文件位于工程的bin/文件夹中,名为<your_project_name>-unsigned.apk。由于apk文件还没有签名,所以你必须手动的使用密钥进行签名,然后使用zipalign进行对齐。

然而,Ant编译脚本也可以替你执行签名和对齐操作,前提是你在build.properties文件中提供了keystore的名字和key的别名。如果提供了这些信息,编译脚本在执行ant release命令时会提示你输入keystorekey的密码,对包进行签名并对齐。最后输出的文件位于工程的bin/文件夹中,名为<your_project_name>-release.apk。如果按照上述自动签名和对齐操作执行,那么,你就可以跳过下面的手动步骤(步骤34)。了解如何在build.properties文件中指定keystorealias,请参考“其它IDE下开发:Release模式编译”。

3.使用密钥签名程序

如果你已经准备好要签名的程序包的话,你可以使用Jarsigner工具进行签名。如“基本设定”中描述的,请确保Jarsigner工具可用。此外,确保包含密钥的keystore可用。

为了签名应用程序,你需要运行Jarsigner,并引用应用程序的apk及包含密钥的keystore。下表列出了你可能使用的选项。

Jarsigner选项

描述

-keystore<keystore-name>.keystore

指定包含密钥的keystore的名字

-verbose

日志输出

-storepass <password>

指定keystore的密码。

基于安全考虑,不要在命令行中包含这一选项,除非你在一个安全的计算机上。如果你不提供,Jarsigner会提示你输入。这样,你的密码就不会储存在shell记录中了

-keypass <password>

指定密钥的密码。

基于安全考虑,不要在命令行中包含这一选项,除非你在一个安全的计算机上。如果你不提供,Jarsigner会提示你输入。这样,你的密码就不会储存在shell记录中了

下面是一个使用Jarsignermy_application.apk进行签名的例子,使用了上面创建的keystore

$ jarsigner -verbose -keystore my-release-key.keystore my_application.apk alias_name

运行上面的示例命令,Jarsigner会提示你输入keystorekey的密码。然后它会修改apk文件,意味着apk文件现在已经签上名了。注意:你可以使用不同的keyapk多次签名。

检验apk文件是否签名,可以使用下面的命令:

$ jarsigner -verify my_signed.apk

如果apk签名正确,Jarsigner输出“jar verified”。如果你想了解更多的细节,你可以尝试这些命令:

$ jarsigner -verify -verbose my_application.apk

或者

$ jarsigner -verify -verbose -certs my_application.apk

上面的命令,添加-certs选项,将会显示“CN=”行,描述谁创建了密钥。

注意:如果你看到“CN=Android Debug”,这意味apk文件使用Android SDK生成的Debug key签的名。如果你想发布你的程序,你必须使用自己的密钥替换Debug key进行签名。

了解更多Jarsigner的信息,请参考http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security

4.对齐APK

一旦你对apk文件使用密钥进行签名后,一定要运行zipalign进行对齐。这个工具能做到让那些未压缩的数据以特定的字节对齐。以4字节对齐能优化性能。当对齐后,Android系统能通过mmap()阅读文件,即使它们包含二进制数据,而不是从包中拷贝所有的数据。好处是在运行程序时减少了随机读取内存的消耗。

zipalignAndroid SDK提供,包含在tools/文件夹下。想对齐签名后的apk,执行:

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

-v标志表示开始日志输出(可选)。4表示对齐的字节(不要使用非4的数字)。第一个文件参数是你的签名后apk(输入),第二个文件参数是目的apk文件(输出)。如果你想覆盖已经存在的apk,添加-f标志。

注意:在你使用zipalign优化包之前,输入的apk必须是使用密钥签名后的。如果在zipalign操作之后再签名,那么对齐操作就白做了。

了解更多信息,请阅读“zipalign”工具的文档。

使用Eclipse/ADT编译和签名

如果你在使用Eclipse/ADT插件,你可以使用导出向导导出一个签名的apk(甚至可以创建一个新的keystore,如果需要的话)。导出向导替你做了所有与KeytoolJarsigner交互的工作,并且使用GUI来签名应用程序,替代了上面提到的手动编译、签名和对齐的操作。一旦向导完成了编译和签名,也还会使用zipalign执行包的对齐操作。由于导出向导要使用KeytooJarsigner。你应该确保它们是可用的,如“签名的基本设定”中描述的那样。

安全储存你的密钥

维护密钥的安全是极其重要的。如果你让其他人使用了你的key,或者你把keystore和密码放在一个不安全的地方以至于第三方人员找到并使用了的话,那么,你的授权认证和用户的信任都将受到连累。

如果第三方没有经过你的允许拿走了你的key,那个人就可以签名并发布应用程序,并恶意替换或攻击你的正版程序。这个人还可以签名并发布应用程序,利用你的名义来攻击其它程序或者系统自身,或者破坏、偷取用户数据。

开发者的名声依赖于正确的储存你的密钥,直到它过期。这里有几个安全储存密钥的提示:

·keykeystore设置强密码。

·当你使用Keytool生成密钥的时候,不要再命令行中添加-storepass-keypass选项。如果你这样做了,在shell记录中就可以获取你的密码。

·相似的,当使用Jarsigner来签名程序时,也不要在命令行中添加-storepass-keypass选项。

·不要把密钥给别人或借给别人,不要让未授权的人知道你的keystorekey的密码。

总而言之,只要你在生成、使用和储存密钥时有安全意识的话,它还是很安全的。

更多相关文章

  1. Android的ADB工具使用
  2. 使用Android内置的Pull解析器解析XML文件
  3. Android(安卓)轻松实现语音朗读
  4. Android应用程序框架层和系统运行库层日志系统源代码分析
  5. android box2d小程序
  6. 10个常见的 Android(安卓)新手误区
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. Android开发Tips(4)
  2. android编辑布局文件时非要降低api level
  3. android adb不常见命令使用
  4. H5混合开发 js与java相互调用
  5. json形式的 Android(安卓)客户端与服务器
  6. Android的状态机模式StateMachine与State
  7. Android学习笔记-Android非布局activity
  8. android multicast 多播(组播)问题
  9. 2.1……Android中的单位简介
  10. Android(安卓)ListView pull up to refre