最近在用Mono开发Android项目时打包APK遇到签名失败,keytool工具错误,一时未解,所以研究用keytool命令生成签名证书并给apk签名,最终成功!闲时将此过程整理成文,以待日后温故知新。
S60 第三版在安全性方面做了比较大的改善,对在系统中安装运行的 第三方软件有更为严格的规定。某些涉及手机软硬件安全/个人信息安全等方面的操作被做了特别的限制(比如随手机开机自动启动就是被限制的功能之一)。应用程序要实现这些"被特别限制"了的功能就必须获得“签名”。也就是说要有人来为这个操作的安全性负责!未经任何签名的程序不能安装运行。 签名(sign):就是在应用程序的特定字段写入特定的标记信息,表示该软件已经通过了签署者的审核。说通俗点就是防止别人篡改你的程序,加入恶意代码,然后在发布,后果可想而知。
1、keytool 是JAVA数据证书的管理工具,keytool将密钥(key)和证书(certificates)存在一个成为keystore的文件中,在keystore中包含两种数据:
密钥实体(keyentity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
可信任的证书实体(trusted certificate entity)——只包含公钥
alias(别名)每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写
JDK中keytool常用命令:
-genkey 在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书
(在用户没有指定生成位置的情况下,keystore会存在用户系统默认目录,对于min 7系统,会生成在C:\Users\Administrator文件名为".keystore)
-alias 产生别名
-keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中
-keyalg 指定密钥的算法 (如RSA,DSA,默认为DSA)
-validity 指定创建的证书有效期多少天
-keysize 指定密钥长度
-storepass 指定密钥库的密码(获取keystore信息所需密码)
-keypass 指定别名条目的密码(私钥密码)
-dname 指定证书拥有者信息 例如: "CN=sagely,OU=atr,O=szu,L=sz,ST=gd,C=cn"
-list 显示密钥库中的证书信息 keytool -list -v -keystore sage(指定keystore) -storepass 密码
-v 显示密钥库中的证书详细信息
-export 将别名指定的证书导出到文件 keytool -export -alias caroot -file caroot.crt
-file 参数指定导出到文件的文件名
-delete 删除密钥库中某条目 keytool -delete -alias sage -keystore sage
-keypasswd 修改密钥库中指定条目口令 keytool -keypasswd -alias sage -keypass .... -new .... -storepass ... -keystore sage
-import 将已签名数字证书导入密钥库 keytool -import -alias sage -keystore sagely -file sagely.crt
导入已签名数字证书用keytool -list -v 以后可以明显发现多了认证链长度,并且把整个CA链全部打印出来。
1、步骤:
a)创建Key
b)使用创建好的key对apk签名
c)优化已签名APK
2、操作:
直接在CMD命令窗口使用keytool的前提是已将jdk安装目录下的bin中的keytool所在目录加入到环境变量Path中,否则在命令窗口欧诺个需要进入到keytool所在目录才能执行以下操作。
a)创建key:
keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore
然后依提示一步步完成其他输入。
b)对为签名APK签名
jarsigner -verbose -keystore android.keystore signerdjar android_signed.apk demo.apk android.keystore
说明:-verbose输出签名详细信息
-keystore android.keystore 密钥库位置
-signedjar android_signed.apk demo.apk android.keystore 正式签名,三个参数依次为签名后最终apk,要签名的apk以及密钥库android.keystore
注意事项:android项目中bin目录下的demo.apk默认是已经使用debug用户签名的,所以不能用上述步骤对此文件再次签名,这种情况对eclipse和VS中的android项目都是一样的。因为我是在VS中做的mono for android项目,所以,我的实际操作是在上述a步骤创建好key后,在vs-->release模式下采用工具-->publish android application-->user existing keystore,然后输入创建好的key信息后打包apk的。而在eclipse下也能直接导出带签名的最终apk,非常方便。
c)优化已签名apk
未签名的apk不能使用也不能优化。而签名之后的apk,谷歌推荐使用zipalign.exe(位于SDK目录下的tool文件夹下)工具对其优化,命令如下:
zipalign -v 4 android_signed.apk final.apk
如上,zipalign能够使apk文件中未压缩的数据在4个字节边界上对齐(4个字节是一个性能很好的值),这样android系统就可以使用mmap()(请自行查阅这个函数的用途)函数读取文件,可以在读取资源上获得较高的性能,
PS:1.在4个字节边界上对齐的意思就是,一般来说,是指编译器吧4个字节作为一个单位来进行读取的结果,这样的话,CPU能够对变量进行高效、快速的访问(较之前不对齐)。
2.对齐的根源:android系统中的Davlik虚拟机使用自己专有的格式DEX,DEX的结构是紧凑的,为了让运行时的性能更好,可以进一步用"对齐"进一步优化,但是大小一般会有所增加。
查阅网上资料,以便深入了解签名的必要性。
你不可能只做一个APP,你可能有一个宏伟的战略工程,想要在生活,服务,游戏,系统各个领域都想插足的话,你不可能只做一个APP,谷歌建议你把你所有的APP都使用同一个签名证书。
使用你自己的同一个签名证书,就没有人能够覆盖你的应用程序,即使包名相同,所以影响有:
1) App升级。 使用相同签名的升级软件可以正常覆盖老版本的软件,否则系统比较发现新版本的签名证书和老版本的签名证书不一致,不会允许新版本安装成功的。
2) App模块化。android系统允许具有相同的App运行在同一个进程中,如果运行在同一个进程中,则他们相当于同一个App,但是你可以单独对他们升级更新,这是一种App级别的模块化思路。
3) 允许代码和数据共享。android中提供了一个基于签名的Permission标签。通过允许的设置,我们可以实现对不同App之间的访问和共享,如下:
AndroidManifest.xml:
其中protectionLevel标签有4种值:normal(缺省值),dangerous, signature,signatureOrSystem。简单来说,normal是低风险的,所有的App不能访问和共享此App。dangerous是高风险的,所有的App都能访问和共享此App。signature是指具有相同签名的App可以访问和共享此App。signatureOrSystem是指系统image中App和具有相同签名的App可以访问和共享此App,谷歌建议不要使用这个选项,因为签名就足够了,一般这个许可会被用在在一个image中需要共享一些特定的功能的情况下。