签名简介

在Android系统中,所有安装到系统的应用程序都必有一个Android数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个permission的protectionLevel为signature,那么就只有那些跟该permission所在的程序拥有同一个数字证书的应用程序才能取得该权限。Android使用Java的数字证书相关的机制来给apk加盖数字证书,要理解Android数字证书,需要先了解以下数字证书的概念和java的数字证书机制。

基础概念:数字证书

数字证实是采用数字手段来证实用户身份的一种方法。数字证书含有两部分数据:一部分是对应主体(单位或个人)的信息,另一部分是这个主体所对应的公钥。即数字证书保存了主体和它的公钥的一一对应关系,用于自我认证(向其他的用户证明自己的身份)。

Java数字证书工具

Java中的keytool.exe可以用来创建数字证书,所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中,证书库中的一条证书包含该条证书的私钥,公钥和对应的数字证书的信息。证书库中的一条证书可以导出数字证书文件,数字证书文件只包括主体信息和对应的公钥。
每一个证书库是一个文件组成,它有访问密码,在首次创建时,它会自动生成证书库,并要求指定访问证书库的密码。
在创建证书的的时候,需要填写证书的一些信息和证书对应的私钥密码。这些信息包括 CN=xx,OU=xx,O=xx,L=xx,ST=xx,C=xx,它们的意思是:
CN
OU
O(Organization组织名称)
L(Locality城市或区域名称)
ST
C(Country国家名称)
可以采用交互式让工具提示输入以上信息,也可以采用参数
-dname "CN=xx,OU=xx,O=xx,L=xx,ST=xx,C=xx"来自动创建。
例如这条命令:
keytool -genkey -alias testCA -keyalg RSA -keysize 1024 -keystore testCALib -validity 3650
在数字证书库testCALib中创建了一个别名为testCA,使用RSA算法加密的,有效期为3650天的数字证书。
证书生成以后,我们可以使用命名将数字证书导出为一个文件。
keytool -export -alias testCA -file testCA.cer -keystore testALib -rfc
有关keytool的其他用法可以查询keytool的帮助文档。
数字证书生成以后,我们需要使用生成的数字证书给程序包签名,这个是使用jarsigner 工具。例如,如果我们有一个android的程序包calendar.apk.,我们就可以使用刚生成的testCA给改程序包签名。
jarsigner -keystore testCALib calendar.apk testCA.

签名的意义

保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序,需要对我们发布的APK文件进行唯一签名,保证我们每次发布的版本的一致性(如自动更新不会因为版本不一致而无法安装)。

Android数字证书概述

Android系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,而不是用来决定最终用户可以安装哪些应用程序。这个数字证书并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。
Android数字证书包含以下几个要点:1. 所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序2. Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证3. 如果要正式发布一个Android应用,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。4. 数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。但过期后无法升级5. Android使用标准的java工具 Keytool and Jarsigner 来生成数字证书,并给应用程序包签名。Android系统不会安装运行任何一款未经数字签名的apk程序,无论是在模拟器上还是在实际的物理设备上。Android的开发工具(ADT插件和Ant)都可以协助开发者给apk程序签名,它们都有两种模式:调试模式(debug mode)和发布模式(release mode)。在调试模式下,android的开发工具会在每次编译时使用调试用的数字证书给程序签名,开发者无须关心。当要发布程序时,开发者就需要使用自己的数字证书给apk包签名,可以有两种方法。
  1. 在命令行下使用JDK中的和Keytool(用于生成数字证书)和Jarsigner(用于使用数字证书签名)来给apk包签名 使用ADT
  2. Export Wizard进行签名(如果没有数字证书可能需要生成数字证书)

签名策略

同一个开发者尽量使用同一个数字证书 同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。
  1. 有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。
  2. 有利于程序的模块化设计和开发。Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序,可以单独对他们升级更新,这是一种App级别的模块化思路。所以开发者可以将自己的程序分模块开发,而用户只需在需要的时候下载适当的模块。
  3. 可以通过权限(permission)的方式在多个程序间共享数据和代码。Android提供了基于数字证书的权限赋予机制(AndroidManifest.xml:

数字证书的有效期

  1. 数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有该数字证书的程序将不能正常升级。
  2. 如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。
  3. Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。

权限

要区分apk运行时的拥有的权限与在文件系统上被访问(读写执行)的权限两个概念

linux文件系统上的权限

-rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
代表的是相应的用户/用户组及其他人对此文件的访问权限,与此文件运行起来具有的权限完全不相关。
比如上面的例子只能说明system用户拥有对此文件的读写执行权限;system组的用户对此文件拥有读、执行权限;其他人对此文件只具有执行权限。
而test.apk运行起来后可以干哪些事情,跟这个就不相关了。
千万不要看apk文件系统上属于system/system用户及用户组,或者root/root用户及用户组,就认为apk具有system或root权限。

Android的权限规则

  1. Android中的apk必须签名

    这种签名不是基于权威证书的,不会决定某个应用允不允许安装,而是一种自签名证书。
    重要的是,android系统有的权限是基于签名的。比如:system等级的权限有专门对应的签名,签名不对,权限也就获取不到。默认生成的APK文件是debug签名的。

  2. 基于UserID的进程级别的安全机制

    进程有独立的地址空间,进程与进程间默认是不能互相访问的,是一种很可靠的保护机制。
    Android通过为每一个安装在设备上的包(apk)分配唯一的Linux userID来实现,名称为”app_”加一个数字,比如app_43。不同的UserID,运行在不同的进程,所以apk之间默认便不能相互访问。
    Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒:
    在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个package需要有相同的签名,否则没有验证也就没有意义了(详见<共享UID>)。
    (这里补充一点:并不是说分配了同样的UserID,两程序就运行在同一进程, 下面为PS指令摘取的,显然,system、app_2分别对应的两个进程的PID都不同)
    User PID PPID
    system 953 883 187340 55052 ffffffff afe0cbcc S system_server
    app_2 1072 883 100264 19564 ffffffff afe0dcc4 S com.android.inputmethod.
    system 1083 883 111808 23192 ffffffff afe0dcc4 S android.process.omsservi
    app_2 1088 883 156464 45720 ffffffff afe0dcc4 S android.process.acore

  3. 默认apk生成的数据对外是不可见的

    实现方法是:Android会为程序存储的数据分配该程序的UserID。借助于Linux严格的文件系统访问权限,便实现了apk之间不能相互访问似有数据的机制。
    例:我的应用创建的一个文件,默认权限如下,可以看到只有UserID为app_21的程序才能读写该文件。
    -rw app_21 app_21 87650 2000-01-01 09:48 test.txt
    如何对外开放:使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE 标记。
    应用创建的任何文件都会被赋予应用的用户标识,并且正常情况下不能被其他包访问。当通过 getSharedPreferences(String,int)、openFileOutput(String、int)或者openOrCreateDatabase(String、int、SQLiteDatabase.CursorFactory)创建一个新文件时,开发者可以同时或分别使用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE 标志允许其他包读/写此文件。当设置了这些标志后,这个文件仍然属于自己的应用程序,但是它的全局读/写和读/写权限已经设置,所以其他任何应用程序可以看到它。

  4. AndroidManifest.xml中的显式权限声明

    Android默认应用是没有任何权限去操作其他应用或系统相关特性的,应用在进行某些操作时都需要显式地去申请相应的权限。
    一般以下动作时都需要申请相应的权限:
    A particular permission may be enforced at a number of places during your program’s operation:
    At the time of a call into the system, to prevent an application from executing certain functions.
    When starting an activity, to prevent applications from launching activities of other applications.
    Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
    When accessing and operating on a content provider.
    Binding or starting a service.
    在应用安装的时候,package installer会检测该应用请求的权限,根据该应用的签名或者提示用户来分配相应的权限。在程序运行期间是不检测权限的。如果安装时权限获取失败,那执行就会出错,不会提示用户权限不够。
    大多数情况下,权限不足导致的失败会引发一个 SecurityException, 会在系统log(system log)中有相关记录。

  5. 权限继承/UserID继承

    当我们遇到apk权限不足时,我们有时会考虑写一个linux程序,然后由apk调用它去完成某个它没有权限完成的事情,很遗憾,这种方法是行不通的。前面讲过,android权限是经营在进程层面的,也就是说一个apk应用启动的子进程的权限不可能超越其父进程的权限(即apk的权限),即使单独运行某个应用有权限做某事,但如果它是由一个apk调用的,那权限就会被限制。实际上,android是通过给子进程分配父进程的UserID实现这一机制的。

常见权限不足问题分析

首先要知道,普通apk程序是运行在非root、非system层级的,也就是说看要访问的文件的权限时,看的是最后三位。另外,通过system/app安装的apk的权限一般比直接安装或adb install安装的apk的权限要高一些。

运行一个android应用程序过程中遇到权限不足,一般分为两种情况:

  1. Log中可明显看到权限不足的提示

    此种情况一般是AndroidManifest.xml中缺少相应的权限设置,查找权限列表就可解决,是最易处理的情况。
    有时权限都加上了,但还是报权限不足,是什么情况呢?
    Android系统有一些API及权限是需要apk具有一定的等级才能运行的。
    比如 SystemClock.setCurrentTimeMillis()修改系统时间,WRITE_SECURE_SETTINGS权限,都是需要有system级的权限才行,也就是说UserID是system.

  2. Log里没有报权限不足,而是一些其他Exception的提示,这也有可能是权限不足造成的。

    比如:我们常会想读/写一个配置文件或其他一些不是自己创建的文件,常会报java.io.FileNotFoundException错误。
    系统认为比较重要的文件一般权限设置的也会比较严格,特别是一些很重要的(配置)文件或目录。

    r–r—- bluetooth bluetooth 935 2010-07-09 20:21 dbus.conf
    drwxrwx–x system system 2010-07-07 02:05 data
    dbus.conf好像是蓝牙的配置文件,从权限上来看,根本就不可能改动,非bluetooth用户连读的权利都没有。
    /data目录下存的是所有程序的私有数据,默认情况下android是不允许普通apk访问/data目录下内容的,通过data目录的权限设置可知,其他用户没有读的权限。
    所以adb普通权限下在data目录下敲ls命令,会得到opendir failed, Permission denied的错误,通过代码file.listfiles()也无法获得data目录下的内容。
    上面两种情况,一般都需要提升apk的权限,目前所知的apk能提升到的权限就是system(具体方法见:

共享UID

安装在设备中的每一个Android包文件(.apk)都会被分配到一个属于自己的统一的Linux用户ID,并且为它创建一个沙箱,以防止影响其他应用程序(或者其他应用程序影响它)。用户ID在应用程序安装到设备中时被分配,并且在这个设备中保持它的永久性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中,所以默认就是可以互相访问任意数据。也可以配置成运行成不同的进程,同时可以访问其他APK的数据目录下的数据库和文件,就像访问本程序的数据一样。对于一个APK来说,如果要使用某个共享UID的话,必须做三步:
  1. 在Manifest节点中增加android:sharedUserId属性,比如android:sharedUserId=”android.uid.system”

  2. 在Android.mk中增加LOCAL_CERTIFICATE的定义。如果增加了上面的属性但没有定义与之对应的LOCAL_CERTIFICATE的话,APK是安装不上去的。提示错误是:Package
    has no signatures that match those in shared user
    android.uid.system;
    ignoring!也就是说,仅有相同签名和相同sharedUserID标签的两个应用程序签名会被分配相同的用户ID。例如所有和media/download相关的APK都使用android.media作为sharedUserId的话,那么它们必须有相同的签名media。

  3. 把APK的源码放到packages/apps/目录下,用mm进行编译。

    举例说明一下:
    系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加 android:sharedUserId=”android.uid.system”,然后在Android.mk中增加 LOCAL_CERTIFICATE := platform。可以参见Settings等
    系统中所有使用android.uid.shared作为共享UID的APK,都会在manifest节点中增加 android:sharedUserId=”android.uid.shared”,然后在Android.mk中增加 LOCAL_CERTIFICATE := shared。可以参见Launcher等
    系统中所有使用android.media作为共享UID的APK,都会在manifest节点中增加 android:sharedUserId=”android.media”,然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以参见Gallery等。

关于签名

build/target/product/security目录中有四组默认签名供Android.mk在编译APK使用:
  1. testkey:普通APK,默认情况下使用。

  2. platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。

  3. shared:该APK需要和home/contacts进程共享数据。

  4. media:该APK是media/download系统中的一环。

应用程序的Android.mk中有一个LOCAL_CERTIFICATE字段,由它指定用哪个key签名,未指定的默认用testkey.

system权限获取

以修改系统时间为例:

  1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId=”android.uid.system”这个属性。
  2. 使用目标系统的platform密钥来重新给apk文件签名。

最后解释一下原理,首先加入android:sharedUserId=”android.uid.system”这个属性。通过Shared User id把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。
只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform key。用这两个key签名后apk才真正可以放入系统进程中。这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8和platform.x509.pem两个文件,要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示”Package … has no signatures that match those in shared user android.uid.system”,这样也是保护了系统的安全。

第三方应用商店的安装权限

经过对第三方AppStore“应用汇”的测试,发现第三方AppStore默认无法获取安装权限,只有设置了“安全-允许安装不是从电子市场获取的的应用程序”(Settings.Secure.INSTALL_NON_MARKET_APPS)才行。默认安装应用程序需要获得android.permission.INSTALL_PACKAGES权限,这个权限只有platform key签名才能获取。如果设置了“安全-允许安装不是从电子市场获取的的应用程序”,系统在安装应用时就不会检查这个权限,第三方AppStore就可以安装应用程序

Android App签名和权限相关推荐

  1. Android App签名的那些事

    App签名 Android App签名的目的是确保App的安装包来自于原创的作者,且App没有被篡改.Android手机是如何设别App来自于原创的作者且没有被篡改呢?请看App签名以及验签原理. A ...

  2. Android APP 默认赋予权限

    Android APP 默认赋予权限 首先在/vendor/xxxx/中创建etc/文件夹 在etc/中创建Android.bp和default-permissions-xxxx.xml文件 Andr ...

  3. Android App签名(证书)校验过程源码分析

      Android App安装是需要证书支持的,我们在Eclipse或者Android Studio中开发App时,并没有注意关于证书的事,也能正确安装App.这是因为使用了默认的debug证书.在A ...

  4. android app没有读写权限设置,Android 6.0以上权限拒绝打开权限设置界面的解决方法...

    本人使用小米手机,打开qq或者微信的时候,某个权限拒绝的话,会提示你开启,点击开启会跳转到app的权限设置界面,当然了,这是国内系统深层定制的原因,也就是说这个界面原声的android没有的!这里以小 ...

  5. android app签名方法

    1.生成签名文件 在android studio 里操作如下: 填完即可. 会产生这个签名文件. 2.签名app 到jdk的bin文件夹下输入下面命令: jarsigner -verbose -key ...

  6. android app签名详解

    本文及文中图片转自:https://mp.weixin.qq.com/s?__biz=MzIwMzYwMTk1NA==&mid=2247493825&idx=1&sn=e926 ...

  7. android 执行shell root权限,Android App 获取root权限后,执行shell命令

    背景: 做一个应用,需求是获取root权限后可以停用/启用某些应用,包括系统应用!停用的应用将不在设置-->应用中展示,大部分系统自带的桌面应该也不会再显示! 如果是用menifest.xml中 ...

  8. Android App签名

    Andriod应用程序如果要在手机或模拟器上安装,必须要有签名! 1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序, ...

  9. Android APP签名和签名等信息查看

    最近在写学校的创新项目,是一个基于定位的签到系统,需要用到百度地图,百度地图SDK的使用需要申请身份,获取key值等,过程中需要提供应用的签名,下面介绍一下签名的使用. 1. 为什么要签名? 发送者的 ...

最新文章

  1. in the java search_Search API – Using scrolls in Java - Elasticsearch Java API 手册
  2. 时间序列预测---差分自回归移动平均模型(ARIMA模型)
  3. FreePascal - 如何在各个平台中安装CodeTyphon!
  4. Java并发编程—Atomic原子类
  5. vs code打开文件显示的中文乱码
  6. P4342:[IOI1998]Polygon(区间dp)
  7. TensorFlow保存和载入训练模型
  8. emd实现信息隐藏_EMD算法原理与实现
  9. ASP.NET调用Oracle分页存储过程并结合ASPnetpager分页控件 实现分页功能
  10. elasticsearch 部署
  11. JavaScript 移动和触摸框架
  12. bootstrapTable 取消 “正在加载中...”
  13. JAVA实用教程(第六版)——期末复习1
  14. JavaScript全套视频教程
  15. ae效果英文版翻译对照表_AE特效中英名字对照表
  16. layui里面layer弹窗渲染layerdate,时间控件不出现,闪现问题,F12才出来
  17. YouTube技术架构
  18. Ieee access投稿---之科研处女作
  19. 如果细节决定成败,那么什么决定细节
  20. Mothur5进阶_Mothur扩增子基因序列分析_基于OTU或ASV的多样性指数分析

热门文章

  1. 热电偶温度采集pid加热控制,高精度adc数据采集继电器输出
  2. 学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。
  3. 中基鸿业工薪家庭如何理财
  4. excel 函数使用
  5. 红蜻蜓利用档案数字化管理,实现业务管理降本增效
  6. 一致性Hash算法及Java实践
  7. 华中科技大学计算机考研资料汇总
  8. Jetson nano开机
  9. Cortana小娜:智能提醒“该出发了”
  10. 【Bug】Could not locate zlibwapi.dll. Please make sure it is in your library path!