Android安全机制探讨

时间:2021-10-23 18:56:35

Android安全机制探讨


一、  详解公钥、私钥和数字证书

加密和认证

  首先我们需要区分加密和认证这两个基本概念。

  加密是将数据资料加密,使得非法用户即使取得加密过的资料,也无法获取正确的资料内容,所以数据加密可以保护数据,防止监听攻击。其重点在于数据的安全性。身份认证是用来判断某个身份的真实性,确认身份后,系统才可以依不同的身份给予不同的权限。其重点在于用户的真实性。两者的侧重点是不同的。

 

 

公钥和私钥

      公钥和私钥就是俗称的不对称加密方式,是从以前的对称加密(使用用户名与密码)方式的提高。

 

      在现代密码*中加密和解密是采用不同的密钥(公开密钥),也就是非对称密钥密码系统,每个通信方均需要两个密钥,即公钥和私钥,这两把密钥可以互为加解密。公钥是公开的,不需要保密,而私钥是由个人自己持有,并且必须妥善保管和注意保密。

 

  公钥私钥的原则:

 

1.一个公钥对应一个私钥。

2.密钥对中,让大家都知道的是公钥,不告诉大家,只有自己知道的,是私钥。

3.如果用其中一个密钥加密数据,则只有对应的那个密钥才可以解密。

4.如果用其中一个密钥可以进行解密数据,则该数据必然是对应的那个密钥进行的加密。

      用电子邮件的方式说明一下原理。

      使用公钥与私钥的目的就是实现安全的电子邮件,必须实现如下目的:

      1. 我发送给你的内容必须加密,在邮件的传输过程中不能被别人看到。

      2. 必须保证是我发送的邮件,不是别人冒充我的。

      要达到这样的目标必须发送邮件的两人都有公钥和私钥。

      公钥,就是给大家用的,你可以通过电子邮件发布,可以通过网站让别人下载,公钥其实是用来加密/验章用的。私钥,就是自己的,必须非常小心保存,最好加上 密码,私钥是用来解密/签章,首先就Key的所有权来说,私钥只有个人拥有。公钥与私钥的作用是:用公钥加密的内容只能用私钥解密,用私钥加密的内容只能 用公钥解密。

      比如说,我要给你发送一个加密的邮件。首先,我必须拥有你的公钥,你也必须拥有我的公钥。

      首先,我用你的公钥给这个邮件加密,这样就保证这个邮件不被别人看到,而且保证这个邮件在传送过程中没有被修改。你收到邮件后,用你的私钥就可以解密,就能看到内容。

      其次我用我的私钥给这个邮件加密,发送到你手里后,你可以用我的公钥解密。因为私钥只有我手里有,这样就保证了这个邮件是我发送的。

 

 

 

      非对称密钥密码的主要应用就是公钥加密和公钥认证,而公钥加密的过程和公钥认证的过程是不一样的,下面我就详细讲解一下两者的区别。

 

 

 

基于公开密钥的加密过程

 

    比如有两个用户Alice和Bob,Alice想把一段明文通过双钥加密的技术发送给Bob,Bob有一对公钥和私钥,那么加密解密的过程如下:

 

1.Bob将他的公开密钥传送给Alice。

2.Alice用Bob的公开密钥加密她的消息,然后传送给Bob。

3.Bob用他的私人密钥解密Alice的消息。

 Alice使用Bob的公钥进行加密,Bob用自己的私钥进行解密。

 

 

 

基于公开密钥的认证过程

 

  身份认证和加密就不同了,主要用户鉴别用户的真伪。这里我们只要能够鉴别一个用户的私钥是正确的,就可以鉴别这个用户的真伪。

 

  还是Alice和Bob这两个用户,Alice想让Bob知道自己是真实的Alice,而不是假冒的,因此Alice只要使用公钥密码学对文件签名发送给Bob,Bob使用Alice的公钥对文件进行解密,如果可以解密成功,则证明Alice的私钥是正确的,因而就完成了对Alice的身份鉴别。整个身份认证的过程如下:

 

1.Alice用她的私人密钥对文件加密,从而对文件签名。

2.Alice将签名的文件传送给Bob。

3.Bob用Alice的公钥解密文件,从而验证签名。

 Alice使用自己的私钥加密,Bob用Alice的公钥进行解密。

 

 

 

根证书

 

       根证书是CA认证中心给自己颁发的证书,是信任链的起始点。安装根证书意味着对这个CA认证中心的信任。

 

 

 

总结

 

 

 

      根据非对称密码学的原理,每个证书持有人都有一对公钥和私钥,这两把密钥可以互为加解密。公钥是公开的,不需要保密,而私钥是由证书持人自己持有,并且必须妥善保管和注意保密。

 

      数字证书则是由证书认证机构(CA)对证书申请者真实身份验证之后,用CA的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖发证书机构的公章)后形成的一个数字文件。CA完成签发证书后,会将证书发布在CA的证书库(目录服务器)中,任何人都可以查询和下载,因此数字证书和公钥一样是公开的。  

 

      可以这样说,数字证书就是经过CA认证过的公钥,而私钥一般情况都是由证书持有者在自己本地生成的,由证书持有者自己负责保管。具体使用时,签名操作是发送方用私钥进行签名,接受方用发送方证书来验证签名;加密操作则是用接受方的证书进行加密,接受方用自己的私钥进行解密。

 

证书作用:

A、           保密性 - 只有收件人才能阅读信息。  

B、  认证性 - 确认信息发送者的身份。   

C、   完整性 - 信息在传递过程中不会被篡改。   

D、           不可抵赖性 - 发送者不能否认已发送的信息。

 

二、  android源码中四组默认签名

a) 使用源码中的默认签名

 

Android 提供了签名的程序signapk.jar ,用法如下:

$ signapk publickey.x509[.pem] privatekey.pk8input.jar output.jar

*.x509.pem 为 x509 格式公钥, pk8 为私钥

 

build/target/product/security 目录中有四组默认签名可选: testkey,platform, shared, media (具体见 README.txt ),应用程序中Android.mk 中有一个 LOCAL_CERTIFICATE 字段,由它指定用哪个 key 签名,未指定的默认用 testkey.

 

b) 在源码中自签名

Android 提供了一个脚本 mkkey.sh (build/target/product/security/mkkey.sh ),用于生成密钥,生成后在应用程序中通过 Android.mk 中的LOCAL_CERTIFICATE 字段指名用哪个签名

 

c) mkkey.sh 介绍

 

i. 生成公钥

openssl genrsa -3-out testkey.pem 2048

其中 -3 是算法的参数,2048 是密钥长度, testkey.pem 是输出的文件

 

ii. 转成 x509 格式(含作者有效期等)

openssl req -new-x509 -key testkey.pem -out testkey.x509.pem -days 10000 -subj‘/C=US/ST=California/L=MountainView/O=Android/OU=Android/CN=Android/emailAddress=android@android.com ’

 

iii. 生成私钥

openssl pkcs8 -intestkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt

把的格式转换成 PKCS #8 ,这里指定了-nocryp ,表示不加密,所以签名时不用输入密码

 

Android源码中四组签名用于给应用程序签名,一个公钥,一个私钥;他们的描述如下:

testkey -- a generic key for packages that do nototherwise specify a key.

platform -- a test key for packages that are part ofthe core platform.

shared -- a test key for things that are shared in thehome/contacts process.

media -- a test key for packages that are part of themedia/download system.

三、Android的接入权限

} 权限主要用来对应用的操作增加限制,防止恶意应用进行非法操作给用户造成敏感数据泄漏和设备被非法控制,防止恶意收费等;

Android的接入权限包括:

1.Normal权限,不会给用户带来实质性的伤害,如调整背光。

2. Dangerous权限,可能会给用户带来潜在性的伤害,如读取电话簿、联网等,系统在安装应用时提示用户。

3. signature权限,具有同一签名的应用才能访问。

4.signatureOrSystem权限,主要被设备商使用,不推荐使用,这种权限需要同一签名或者System的权限,如:android.permission.REBOOT。

 

四、android apk 为什么需要签名 及怎样签名

      所有的Android应用程序都要求开发人员用一个证书进行数字签名,anroid系统不会安装没有进行签名的由于程序。

    平时我们的程序可以在模拟器上安装并运行,是因为在应用程序开发期间,由于是以Debug面试进行编译的,因此ADT根据会自动用默认的密钥和证书来进行签名,而在以发布模式编译时,apk文件就不会得到自动签名,这样就需要进行手工签名。

    给apk签名可以带来以下好处:

    1. 应用程序升级:如果你希望用户无缝升级到新的版本,那么你必须用同一个证书进行签名。这是由于只有以同一个证书签名,系统才会允许安装升级的应用程序。如果你采用了不同的证书,那么系统会要求你的应用程序采用不同的包名称,在这种情况下相当于安装了一个全新的应用程序。如果想升级应用程序,签名证书要相同,包名称要相同!

    2.应用程序模块化:Android系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序,此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块

    3.代码或者数据共享:Android提供了基于签名的权限机制,那么一个应用程序就可以为另一个以相同证书签名的应用程序公开自己的功能。以同一个证书对多个应用程序进行签名,利用基于签名的权限检查,你就可以在应用程序间以安全的方式共享代码和数据了。

    不同的应用程序之间,想共享数据,或者共享代码,那么要让他们运行在同一个进程中,而且要让他们用相同的证书签名。

 

 

Android签名方式可划分为两种:

(1)ROM签名机制;

(2)第三方APK签名机制。

 

Android APK实际上是一个jar包,而jar包又是一个zip包。APK包的签名实际上使用的是jar包的签名机制:在zip中添加一个META的子目录,其中存放签名信息;而签名方法是为zip包中的每个文件计算其HASH值,得到签名文件(*.sf),然后对签名文件(.sf)进行签名并把签名保存在签名块文件(*.dsa)中。

 

(1)ROM签名机制;

 

在编译Android源码生成ROM的过程中,会使用build/target/product/security目录中的4个key(media,platform, shared, testkey)来对apk进行签名。其中,*.pk8是二进制形式(DER)的私钥,*.x509.pem是对应的X509公钥证书(BASE64编码)。

 

(2)第三方APK签名机制。

对于第三方应用开发者而言,对APK签名相对要简单得多。第三方应用开发一般采用JDK中的keytool和jarsigner来完成签名密钥的管理和APK的签名。

 

使用keytool来生成存储有公私钥对的keystore:

$ keytool -genkey -v -keystore my-release-key.keystore-alias mykey -keyalg RSA -keysize 2048 -validity 10000

 

查看生成的密钥信息:

$ keytool -list -keystore my-release-key.keystore-alias mykey -v

or,

$ keytool -list -keystore my-release-key.keystore-alias mykey -rfc

(注:获取Base64格式的公钥证书,RFC 1421)

 

导出公钥证书:

$ keytool -export -keystore mystore -alias mykey -filemy.der

(注:二进制格式公钥证书,DER)

$ keytool -export -keystore mystore -alias mykey -filemy.pem -rfc

(注:Base64格式公钥证书,PEM)

 

对APK进行签名:

$ jarsigner -verbose -keystore my-release-key.keystoremy_application.apk mykey

 

验证签名:

$ jarsigner -verify -verbose -certs my_application.apk

 

 

四、对android安全机制总结

      个人理解android安全机制基于linux,又在进行了自己扩展!

 

(1)、基于linux的安全机制

A、    linux文件系统上的权限

-rwxr-x--xsystem   system       4156 2010-04-30 16:13 test.apk

代表的是相应的用户/用户组及其他人对此文件的访问权限,与此文件运行起来具有的权限完全不相关。

 

B、基于UserID的进程级别的安全机制

进程有独立的地址空间,进程与进程间默认是不能互相访问的,是一种很可靠的保护机制。

Android通过为每一个安装在设备上的包(apk)分配唯一的linuxuserID来实现,名称为"app_"加一个数字,比如app_43

不同的UserID,运行在不同的进程,所以apk之间默认便不能相互访问。

 

Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒。

在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,

系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个package需要有相同的签名,否则没有验证也就没有意义了。

 

(1)、android自己的扩展

 

A、       android签名机制

每个apk在发布前要进行签名,只有签名apk才能安装。当别人更改apk的内容必须重新签名,但是这个签名和原来是不一样的。

举个简单的例子,某个应用要获得system权限,他就必须用系统内的platform进行签名,然后在AndroidManifest.xml中利用sharedUserId = system进行声明,才能正常安装使用;若有人更改了此应用他想让应用可用必须拿到platform的证书才可能;这也就保证了系统安全性!

 

 

 

B、       AndroidManifest.xml中的显式权限声明机制

如要用socket等网络通信,则必须在AndroidManifest.xml声明:<uses-permissionandroid:name="android.permission.INTERNET" />

 

在应用安装的时候,packageinstaller会检测该应用请求的权限,根据该应用的签名或者提示用户来分配相应的权限。

在程序运行期间是不检测权限的。如果安装时权限获取失败,那执行就会出错,不会提示用户权限不够。

 

在系统源码下可以参照文件:

frameworks/base/core/res/AndroidManifest.xml