参考链接:

安卓证书相关验证机制:
https://duanqz.github.io/2017-09-01-Android-Digital-Signature
(部分内容不准确)

关于META-INF文件含义:
https://blog.csdn.net/diaoxuesong/article/details/78668659

关于V1 V2 V3签名机制:
https://zhuanlan.zhihu.com/p/108034286

数字证书原理:
https://network.51cto.com/article/628890.html

数字证书的结构:https://www.cnblogs.com/hyddd/archive/2009/01/07/1371292.html

关于CERT.RSA全部内容解析:
https://blog.csdn.net/diaoxuesong/article/details/78668659

安卓apk证书原理及实验验证

1. 数字签名

  • 对待发送的数据明文进行Hash,通常可采用MD5或SHA算法,然后采用私钥对Hash值进行加密,得到签名。将数据明文和签名一同发送出去。
    (为什么要先对原始数据进行Hash后再用私钥加密呢?因为原数据可能比较大,直接使用私钥加密将会非常耗时。)

  • 接收数据以后,会经过签名验证,其实就是比较两个Hash值:采用同样的Hash算法对数据明文进行哈希,得到一个Hash值;采用公钥对签名进行解密后,得到另一个Hash值。如果两个Hash值相同,则说明数据没有被篡改而且来源可信

2. keytool

keytool是JDK的一个工具,用于密钥和证书的管理。
keytool的主要操作对象是keystore文件,该文件一般以.keystore或.jks(Java KeyStore)为后缀名。
keystore可以存储多个密钥对(Key Pair),每一个密钥对包含私钥(Private Key)和多个证书(Certificate):

3. 证书(Certificate)

证书就是对公钥再次私钥签名产生的结果。证书中保存着被签名的公钥签名

3.1 证书认证机构CA(Certificate Authority)和证书链(Certificate Chain)

上述证书的生成过程会导致一个无限的链条:要得到证书,就需要对公钥A进行私钥B签名,并发布公钥B。这样就有两个公钥了:证书本身的公钥(即证书中的Public Key,用公钥A表示)和私钥B所对应的公钥(用公钥B表示)。

要保证公钥B的合法性,我们可以对公钥B再进行私钥C签名,这就又需要发布一个新的公钥C,…,公钥合法性的保证就像链条一样。要打破这个无限的链条,就需要有一个权威机构,来统一颁发证书,这个机构就是CA(Certificate Authority)。

CA的公钥被保存在OS中,被认为是可信的。

光靠一个CA是忙不过来的,CA得授权一些代理,这些代理也可以颁发证书,代理颁发的证书也被认为是合法可信的,这就形成了证书链。

keystore文件的结构:一个私钥(Private Key)与多个证书(Certificates)组成密钥对(Key Pair),其实多个证书的结构就是证书链

4. keystore

如果将keystore看做密钥和证书管理的数据库,那么keytool就是这个数据库增、删、改、查的接口。

5. Android V1签名方案

  • 应用层面:Android对APK的签名要求

    Android拒绝安装没有签名的APK
    Android并不校验证书的合法性(这与https网站证书不一样,https网站证书是要校验签发者的合法性的)
    当签名不匹配时,APK升级会失败

  • 系统层面:Android基于数字签名的一些机制
    编译Android系统时,会根据不同应用的类型进行签名
    Android基于数字签名来判定是否给应用授权
    Android基于数字签名来标记APK的SELinux Lable

6. META-INF目录

给定一个Apk文件,解压,可以看到一个META-INF文件夹,在该文件夹下有三个文件:分别为MANIFEST.MF、CERT.SF和CERT.RSA。

其中MANIFEST.MF名称基本固定,CERT.SF和CERT.RSA可能被换成其他名称(例如微信app中是COM_TENC.SF和COM_TENC.RSA)。


(实测一些APK中用的不是SHA-1,而是SHA-256)

也就是说,CERT.RSA中包含一个证书和一个签名,CERT.RSA并不是一个单纯的证书。

6.1 MANIFEST.MF文件

MANIFEST.MF:记录了APK中每一个文件的摘要

Manifest-Version: 1.0
Built-By: Generated-by-ADT
Created-By: Android Gradle 3.4.2Name: AndroidManifest.xml
SHA-256-Digest: 4Gyn/1pQJm4vo9BPrcOhNA9dqX0xN+Ilux6qDn1f24I=Name: META-INF/androidx.activity_activity.version
SHA-256-Digest: WYVJhIUxBN9cNT4vaBoV/HkkdC+aLkaMKa8kjc5FzgM=Name: META-INF/androidx.annotation_annotation-experimental.version
SHA-256-Digest: WYVJhIUxBN9cNT4vaBoV/HkkdC+aLkaMKa8kjc5FzgM=Name: META-INF/androidx.appcompat_appcompat-resources.version
SHA-256-Digest: HltRzeUVOWqfp2KQnPjKZYTMxWSzJdLuvup2F1/pXE0=Name: META-INF/androidx.appcompat_appcompat.version
SHA-256-Digest: HltRzeUVOWqfp2KQnPjKZYTMxWSzJdLuvup2F1/pXE0=Name: META-INF/androidx.arch.core_core-runtime.version
SHA-256-Digest: wo/MpTY3vIjhJK8XJd8Ty5jGne3v1i+zzb4c22t2BiQ=…………

6.2 CERT.SF文件

CERT.SF:对MANIFEST.MF计算摘要,结果存放在SHA-256-Digest-Manifest;同时对MANIFEST.MF中每一项计算摘要,结果存放在CERT.SF各项中。

Signature-Version: 1.0
Created-By: 1.0 (Android)
SHA-256-Digest-Manifest: ifpWUlrHBqAXmGWiygrMlMr4BL+9Z+J1xzN6IAKIi7U=
X-Android-APK-Signed: 2Name: AndroidManifest.xml
SHA-256-Digest: FM8SO8spjSfyYXZCcMfhl93XRKbKItHolj1eOAaLnx4=Name: META-INF/androidx.activity_activity.version
SHA-256-Digest: Yu1eiqd7wti3kPabgLC0lsO+1ns/UAhiPGUExHOxH/w=Name: META-INF/androidx.annotation_annotation-experimental.version
SHA-256-Digest: Lxz3EbTZKQ+6YHD56UXKdC4eR6Vt/RCS/mhbehwNKY0=Name: META-INF/androidx.appcompat_appcompat-resources.version
SHA-256-Digest: d8qnGN0xpQnZXwhik1KeeAcyufb6b2l+Ods8bsHKkVE=Name: META-INF/androidx.appcompat_appcompat.version
SHA-256-Digest: YwDR0Rxo15s+KFBZKd2nWg6Xm4mF+YmpBoHOItYOSoU=Name: META-INF/androidx.arch.core_core-runtime.version
SHA-256-Digest: PjygIQMN5T6nIKT/hi5PFaxVcEB+W20fr4f0g2n7jrg=
…………

可以看出其中多出一项SHA-256-Digest-Manifest(值为ifpWUlrHBqAXmGWiygrMlMr4BL+9Z+J1xzN6IAKIi7U=)。这个是对MANIFEST.MF文件的SHA256值经Base64编码得到的。

验证过程如下:

利用在线工具(该工具可离线保存),计算MANIFEST.MF文件的SHA256值:89fa56525ac706a0179865a2ca0acc94caf804bfbd67e275c7337a2002888bb5

利用在线工具,求出SHA256值(16进制形式)的Base64编码结果:ifpWUlrHBqAXmGWiygrMlMr4BL+9Z+J1xzN6IAKIi7U=

该值与CERT.SF中的SHA-256-Digest-Manifest相同。

6.3 CERT.RSA文件

CERT.RSA:主要内容是对CERT.SF的私钥A签名(对CERT.SF的摘要的私钥A加密) 和 证书(用于保存公钥A) 。RSA后缀表示签名是基于RSA算法生成的。

证书的本质作用是保存公钥A。同时,证书具备可验证性(在某些额外信息被获取的情况下,用户可以判定证书是否是合法的)。

注意,CERT.RSA是三者中唯一用到私钥的。


6.3.1 证书部分分析

证书保存了:{公钥A+相关信息}{公钥A+相关信息}的私钥B签名结果(和签名算法)。公钥A和私钥A是一对,公钥B和私钥B是一对。当需要验证证书的合法性时,用户从某些途径获取到公钥B(通常是通过上一级证书),而后对 {公钥A+相关信息}的私钥B签名结果 进行解密,得到摘要1;对 {公钥A+相关信息} 计算摘要,得到摘要2;比较摘要1和摘要2是否相同。若相同,则说明证书是可信的。

使用Openssl可以提取其中证书部分内容:

openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text > CERT.RSA-cert.txt

内容如下:

Certificate:Data:Version: 3 (0x2)Serial Number: 33548542 (0x1ffe8fe)Signature Algorithm: sha256WithRSAEncryptionIssuer: C=CNValidityNot Before: Dec 20 04:41:56 2018 GMTNot After : Dec 14 04:41:56 2043 GMTSubject: C=CNSubject Public Key Info:Public Key Algorithm: rsaEncryptionPublic-Key: (2048 bit)Modulus:00:dd:3f:31:51:7f:b3:2f:dd:07:9c:6f:66:3d:eb:17:84:6d:7a:19:1f:bd:63:07:e3:be:30:41:09:a3:84:e7:ab:7f:4b:88:0c:b6:27:3d:38:e6:28:3b:60:ac:19:a9:98:cd:0f:3c:24:67:47:5f:f8:11:b1:e6:00:eb:b0:a4:97:ff:db:db:1f:f8:e8:f7:74:66:51:e2:46:7a:8b:ea:99:28:72:6e:83:f2:d3:50:0c:7e:aa:e5:8a:58:03:98:e9:04:cd:1f:55:39:64:88:b8:92:99:7c:ec:3f:a3:b8:68:44:df:f0:70:b1:2c:50:d6:e8:be:82:3b:20:b6:04:cd:37:e1:1a:43:9b:7e:b5:64:86:8e:ab:8f:8a:c1:86:7d:d8:cb:c7:a3:0c:38:75:01:f4:ec:ad:ec:f5:5c:22:33:80:d6:d9:40:69:dc:f2:d0:7d:19:69:8b:69:f8:48:b3:6f:b0:3c:83:95:17:6d:5b:21:34:64:61:4a:f8:f3:80:fe:e7:f3:2e:7b:86:4a:c8:f7:e2:e0:cd:ff:4f:e3:ad:d9:18:58:fb:cc:7e:29:ff:a1:b8:20:37:25:31:cb:c1:08:84:a2:07:08:35:4f:c9:52:28:c4:56:6a:59:92:bd:ea:3d:47:41:80:1b:a5:0d:f1:f9:52:27:54:63:d4:2fExponent: 65537 (0x10001)X509v3 extensions:X509v3 Subject Key Identifier:07:8C:E8:A0:26:83:A6:E8:5D:C1:84:E7:C2:D4:45:8E:A4:D8:62:5ASignature Algorithm: sha256WithRSAEncryptionSignature Value:3c:0c:03:7f:5c:20:92:0d:f1:a7:9a:35:77:23:b9:f2:d4:bc:76:81:f6:2a:4b:6e:ac:7b:e7:e1:b4:c2:5b:e2:56:b5:cb:33:c4:d6:5e:12:64:df:5a:a6:0c:3d:e6:74:e8:2b:62:3f:7f:0a:16:51:51:ce:9c:f2:c1:88:6c:71:2b:73:53:0a:09:1c:60:86:5d:6f:94:9e:60:0d:dd:a8:f6:e6:51:bf:13:d7:d9:38:81:ea:4b:88:87:20:b0:bf:23:93:3c:9b:85:43:f8:81:f8:e2:ee:0d:24:6b:48:c9:0b:e7:3c:eb:2d:a9:68:04:aa:44:6c:b0:59:80:2b:3c:7e:ba:70:35:b5:22:32:d7:bf:3f:5b:7b:fb:bb:bf:ae:b0:78:8e:4e:5a:87:2c:1a:b9:8f:1b:f9:1b:01:15:b5:fb:9a:51:53:f6:a2:8b:93:84:37:f5:93:b9:f3:06:4d:37:10:21:f8:e0:c8:83:1e:a4:f1:75:64:41:59:1b:68:c2:26:e3:9b:c0:8c:d1:61:6c:62:bb:5b:fc:8f:d4:ee:e5:c2:97:6d:7a:e0:01:b9:7c:08:7e:10:59:f6:4b:d7:7a:9f:c1:d6:99:c7:dd:89:ff:a2:1c:13:53:b2:5f:09:5a:82:1d:b4:bf:59:63:bb:66:a6:88:0a:4b:a2:f4:47


其中:

Signature Value( 3C 0C 03 7F …… 47)是 {公钥A+相关信息}的私钥B签名结果,用于验证证书的可信性,这里暂时不涉及

使用JEB也可以查看Signature Value:

Modulus(模数)和Exponent(指数)共同构成公钥。
Modulus 为:

DD3F31517FB32FDD079C6F663DEB17846D7A191FBD6307E3BE304109A384E7AB7F4B880CB6273D38E6283B60AC19A998CD0F3C2467475FF811B1E600EBB0A497FFDBDB1FF8E8F7746651E2467A8BEA9928726E83F2D3500C7EAAE58A580398E904CD1F55396488B892997CEC3FA3B86844DFF070B12C50D6E8BE823B20B604CD37E11A439B7EB564868EAB8F8AC1867DD8CBC7A30C387501F4ECADECF55C223380D6D94069DCF2D07D19698B69F848B36FB03C8395176D5B213464614AF8F380FEE7F32E7B864AC8F7E2E0CDFF4FE3ADD91858FBCC7E29FFA1B820372531CBC10884A20708354FC95228C4566A5992BDEA3D4741801BA50DF1F952275463D42F

Exponent 为:65537 (0x10001)

通过在线工具生成PEM格式的RSA公钥:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3T8xUX+zL90HnG9mPesX
hG16GR+9YwfjvjBBCaOE56t/S4gMtic9OOYoO2CsGamYzQ88JGdHX/gRseYA67Ck
l//b2x/46Pd0ZlHiRnqL6pkocm6D8tNQDH6q5YpYA5jpBM0fVTlkiLiSmXzsP6O4
aETf8HCxLFDW6L6COyC2BM034RpDm361ZIaOq4+KwYZ92MvHoww4dQH07K3s9Vwi
M4DW2UBp3PLQfRlpi2n4SLNvsDyDlRdtWyE0ZGFK+POA/ufzLnuGSsj34uDN/0/j
rdkYWPvMfin/obggNyUxy8EIhKIHCDVPyVIoxFZqWZK96j1HQYAbpQ3x+VInVGPU
LwIDAQAB
-----END PUBLIC KEY-----

6.3.2 对CERT.SF的私钥A签名部分分析

使用Openssl查看CERT.RSA中全部内容:

openssl asn1parse -inform DER -in CERT.RSA -dump > CERT.RSA.txt
    0:d=0  hl=4 l=1081 cons: SEQUENCE          4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData15:d=1  hl=4 l=1066 cons: cont [ 0 ]        19:d=2  hl=4 l=1062 cons: SEQUENCE          23:d=3  hl=2 l=   1 prim: INTEGER           :0126:d=3  hl=2 l=  15 cons: SET               28:d=4  hl=2 l=  13 cons: SEQUENCE          30:d=5  hl=2 l=   9 prim: OBJECT            :sha25641:d=5  hl=2 l=   0 prim: NULL              43:d=3  hl=2 l=  11 cons: SEQUENCE          45:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data56:d=3  hl=4 l= 701 cons: cont [ 0 ]        60:d=4  hl=4 l= 697 cons: SEQUENCE          64:d=5  hl=4 l= 417 cons: SEQUENCE          68:d=6  hl=2 l=   3 cons: cont [ 0 ]        70:d=7  hl=2 l=   1 prim: INTEGER           :0273:d=6  hl=2 l=   4 prim: INTEGER           :01FFE8FE79:d=6  hl=2 l=  13 cons: SEQUENCE          81:d=7  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption92:d=7  hl=2 l=   0 prim: NULL              94:d=6  hl=2 l=  13 cons: SEQUENCE          96:d=7  hl=2 l=  11 cons: SET               98:d=8  hl=2 l=   9 cons: SEQUENCE          100:d=9  hl=2 l=   3 prim: OBJECT            :countryName105:d=9  hl=2 l=   2 prim: PRINTABLESTRING   :CN109:d=6  hl=2 l=  30 cons: SEQUENCE          111:d=7  hl=2 l=  13 prim: UTCTIME           :181220044156Z126:d=7  hl=2 l=  13 prim: UTCTIME           :431214044156Z141:d=6  hl=2 l=  13 cons: SEQUENCE          143:d=7  hl=2 l=  11 cons: SET               145:d=8  hl=2 l=   9 cons: SEQUENCE          147:d=9  hl=2 l=   3 prim: OBJECT            :countryName152:d=9  hl=2 l=   2 prim: PRINTABLESTRING   :CN156:d=6  hl=4 l= 290 cons: SEQUENCE          160:d=7  hl=2 l=  13 cons: SEQUENCE          162:d=8  hl=2 l=   9 prim: OBJECT            :rsaEncryption173:d=8  hl=2 l=   0 prim: NULL              175:d=7  hl=4 l= 271 prim: BIT STRING        0000 - 00 30 82 01 0a 02 82 01-01 00 dd 3f 31 51 7f b3   .0.........?1Q..0010 - 2f dd 07 9c 6f 66 3d eb-17 84 6d 7a 19 1f bd 63   /...of=...mz...c0020 - 07 e3 be 30 41 09 a3 84-e7 ab 7f 4b 88 0c b6 27   ...0A......K...'0030 - 3d 38 e6 28 3b 60 ac 19-a9 98 cd 0f 3c 24 67 47   =8.(;`......<$gG0040 - 5f f8 11 b1 e6 00 eb b0-a4 97 ff db db 1f f8 e8   _...............0050 - f7 74 66 51 e2 46 7a 8b-ea 99 28 72 6e 83 f2 d3   .tfQ.Fz...(rn...0060 - 50 0c 7e aa e5 8a 58 03-98 e9 04 cd 1f 55 39 64   P.~...X......U9d0070 - 88 b8 92 99 7c ec 3f a3-b8 68 44 df f0 70 b1 2c   ....|.?..hD..p.,0080 - 50 d6 e8 be 82 3b 20 b6-04 cd 37 e1 1a 43 9b 7e   P....; ...7..C.~0090 - b5 64 86 8e ab 8f 8a c1-86 7d d8 cb c7 a3 0c 38   .d.......}.....800a0 - 75 01 f4 ec ad ec f5 5c-22 33 80 d6 d9 40 69 dc   u......\"3...@i.00b0 - f2 d0 7d 19 69 8b 69 f8-48 b3 6f b0 3c 83 95 17   ..}.i.i.H.o.<...00c0 - 6d 5b 21 34 64 61 4a f8-f3 80 fe e7 f3 2e 7b 86   m[!4daJ.......{.00d0 - 4a c8 f7 e2 e0 cd ff 4f-e3 ad d9 18 58 fb cc 7e   J......O....X..~00e0 - 29 ff a1 b8 20 37 25 31-cb c1 08 84 a2 07 08 35   )... 7%1.......500f0 - 4f c9 52 28 c4 56 6a 59-92 bd ea 3d 47 41 80 1b   O.R(.VjY...=GA..0100 - a5 0d f1 f9 52 27 54 63-d4 2f 02 03 01 00 01      ....R'Tc./.....450:d=6  hl=2 l=  33 cons: cont [ 3 ]        452:d=7  hl=2 l=  31 cons: SEQUENCE          454:d=8  hl=2 l=  29 cons: SEQUENCE          456:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Identifier461:d=9  hl=2 l=  22 prim: OCTET STRING      0000 - 04 14 07 8c e8 a0 26 83-a6 e8 5d c1 84 e7 c2 d4   ......&...].....0010 - 45 8e a4 d8 62 5a                                 E...bZ485:d=5  hl=2 l=  13 cons: SEQUENCE          487:d=6  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption498:d=6  hl=2 l=   0 prim: NULL              500:d=5  hl=4 l= 257 prim: BIT STRING        0000 - 00 3c 0c 03 7f 5c 20 92-0d f1 a7 9a 35 77 23 b9   .<...\ .....5w#.0010 - f2 d4 bc 76 81 f6 2a 4b-6e ac 7b e7 e1 b4 c2 5b   ...v..*Kn.{....[0020 - e2 56 b5 cb 33 c4 d6 5e-12 64 df 5a a6 0c 3d e6   .V..3..^.d.Z..=.0030 - 74 e8 2b 62 3f 7f 0a 16-51 51 ce 9c f2 c1 88 6c   t.+b?...QQ.....l0040 - 71 2b 73 53 0a 09 1c 60-86 5d 6f 94 9e 60 0d dd   q+sS...`.]o..`..0050 - a8 f6 e6 51 bf 13 d7 d9-38 81 ea 4b 88 87 20 b0   ...Q....8..K.. .0060 - bf 23 93 3c 9b 85 43 f8-81 f8 e2 ee 0d 24 6b 48   .#.<..C......$kH0070 - c9 0b e7 3c eb 2d a9 68-04 aa 44 6c b0 59 80 2b   ...<.-.h..Dl.Y.+0080 - 3c 7e ba 70 35 b5 22 32-d7 bf 3f 5b 7b fb bb bf   <~.p5."2..?[{...0090 - ae b0 78 8e 4e 5a 87 2c-1a b9 8f 1b f9 1b 01 15   ..x.NZ.,........00a0 - b5 fb 9a 51 53 f6 a2 8b-93 84 37 f5 93 b9 f3 06   ...QS.....7.....00b0 - 4d 37 10 21 f8 e0 c8 83-1e a4 f1 75 64 41 59 1b   M7.!.......udAY.00c0 - 68 c2 26 e3 9b c0 8c d1-61 6c 62 bb 5b fc 8f d4   h.&.....alb.[...00d0 - ee e5 c2 97 6d 7a e0 01-b9 7c 08 7e 10 59 f6 4b   ....mz...|.~.Y.K00e0 - d7 7a 9f c1 d6 99 c7 dd-89 ff a2 1c 13 53 b2 5f   .z...........S._00f0 - 09 5a 82 1d b4 bf 59 63-bb 66 a6 88 0a 4b a2 f4   .Z....Yc.f...K..0100 - 47                                                G761:d=3  hl=4 l= 320 cons: SET               765:d=4  hl=4 l= 316 cons: SEQUENCE          769:d=5  hl=2 l=   1 prim: INTEGER           :01772:d=5  hl=2 l=  21 cons: SEQUENCE          774:d=6  hl=2 l=  13 cons: SEQUENCE          776:d=7  hl=2 l=  11 cons: SET               778:d=8  hl=2 l=   9 cons: SEQUENCE          780:d=9  hl=2 l=   3 prim: OBJECT            :countryName785:d=9  hl=2 l=   2 prim: PRINTABLESTRING   :CN789:d=6  hl=2 l=   4 prim: INTEGER           :01FFE8FE795:d=5  hl=2 l=  13 cons: SEQUENCE          797:d=6  hl=2 l=   9 prim: OBJECT            :sha256808:d=6  hl=2 l=   0 prim: NULL              810:d=5  hl=2 l=  13 cons: SEQUENCE          812:d=6  hl=2 l=   9 prim: OBJECT            :rsaEncryption823:d=6  hl=2 l=   0 prim: NULL              825:d=5  hl=4 l= 256 prim: OCTET STRING      0000 - 13 6e 93 d0 23 ce b7 33-d5 ed fa e7 cd 10 cf 56   .n..#..3.......V0010 - 77 c5 e5 f6 03 07 49 31-70 d3 ad 1f 01 69 e0 e7   w.....I1p....i..0020 - 31 0b 9b 26 57 7a e0 b1-66 79 79 8e af 57 ac 44   1..&Wz..fyy..W.D0030 - c5 88 d5 50 cd ba 5e f9-0e e9 77 17 30 50 29 28   ...P..^...w.0P)(0040 - 08 aa 98 20 3b 56 2f f6-10 2e e4 d8 2b 29 e4 6e   ... ;V/.....+).n0050 - 9d 4e 96 e2 03 0c df af-9a b4 bb fd a8 9c f7 39   .N.............90060 - 29 45 23 3f 01 13 0e 3d-b7 02 a2 d8 53 6a eb aa   )E#?...=....Sj..0070 - 21 71 9a af 0f 35 5b ec-26 51 d0 22 96 df 8d 14   !q...5[.&Q."....0080 - 88 98 d4 d4 de 29 9d 77-17 96 e2 e3 bd cc b7 f0   .....).w........0090 - 61 17 48 a8 33 f5 2e 40-77 b2 42 e1 cf db ef ac   a.H.3..@w.B.....00a0 - 65 a2 1e 10 2e a2 47 8f-b6 9b 7b 3b 84 43 bd 92   e.....G...{;.C..00b0 - 57 72 ca e5 f8 d9 72 7d-3c 11 d7 4b b9 b0 1f ca   Wr....r}<..K....00c0 - 23 e3 07 bb d0 60 4d 4c-0c 28 11 bd 79 8a 2e b8   #....`ML.(..y...00d0 - ce 75 6c bb 53 15 36 79-25 39 6c 55 66 97 87 5a   .ul.S.6y%9lUf..Z00e0 - be 8e ad 29 cc 99 f9 fa-c0 c7 fe 9d 7b f9 47 22   ...)........{.G"00f0 - da ad 6d 90 66 61 52 45-95 cf 15 18 3c f3 51 58   ..m.faRE....<.QX

其中00 3c 0c ... 47是对证书加密的结果,用于验证证书的可信性,这里不涉及。

末尾的16进制数13 6e ... 58对CERT.SF的私钥A签名,也就是:

136E93D023CEB733D5EDFAE7CD10CF5677C5E5F60307493170D3AD1F0169E0E7310B9B26577AE0B16679798EAF57AC44C588D550CDBA5EF90EE977173050292808AA98203B562FF6102EE4D82B29E46E9D4E96E2030CDFAF9AB4BBFDA89CF7392945233F01130E3DB702A2D8536AEBAA21719AAF0F355BEC2651D02296DF8D148898D4D4DE299D771796E2E3BDCCB7F0611748A833F52E4077B242E1CFDBEFAC65A21E102EA2478FB69B7B3B8443BD925772CAE5F8D9727D3C11D74BB9B01FCA23E307BBD0604D4C0C2811BD798A2EB8CE756CBB5315367925396C556697875ABE8EAD29CC99F9FAC0C7FE9D7BF94722DAAD6D906661524595CF15183CF35158

使用在线工具对该值进行解密。
其中,公钥是PEM格式的,由前文提到的Modulus和Exponent生成,如下:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3T8xUX+zL90HnG9mPesX
hG16GR+9YwfjvjBBCaOE56t/S4gMtic9OOYoO2CsGamYzQ88JGdHX/gRseYA67Ck
l//b2x/46Pd0ZlHiRnqL6pkocm6D8tNQDH6q5YpYA5jpBM0fVTlkiLiSmXzsP6O4
aETf8HCxLFDW6L6COyC2BM034RpDm361ZIaOq4+KwYZ92MvHoww4dQH07K3s9Vwi
M4DW2UBp3PLQfRlpi2n4SLNvsDyDlRdtWyE0ZGFK+POA/ufzLnuGSsj34uDN/0/j
rdkYWPvMfin/obggNyUxy8EIhKIHCDVPyVIoxFZqWZK96j1HQYAbpQ3x+VInVGPU
LwIDAQAB
-----END PUBLIC KEY-----

解密结果:

解密得到的数据为:

30 31 30 0D 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 A2 B4 DB 1A 50 BE BC 75 40 5B AB E5 C1 3B 96 CF DF 92 E6 50 65 4E DB 6F 56 46 E0 2B 41 B2 C1 E9

其中的A2 B4 DB 1A 50 BE BC 75 40 5B AB E5 C1 3B 96 CF DF 92 E6 50 65 4E DB 6F 56 46 E0 2B 41 B2 C1 E9就是CERT.SF的SHA256摘要

验证如下:


6.3.3 从CERT.RSA中提取证书指纹(Fingerprint)

证书指纹是对证书的哈希值。

使用keytool也可以查看CERT.RSA中的证书指纹:

keytool --printcert -file CERT.RSA
所有者: C=CN
发布者: C=CN
序列号: 1ffe8fe
生效时间: Thu Dec 20 12:41:56 CST 2018, 失效时间: Mon Dec 14 12:41:56 CST 2043
证书指纹:SHA1: 8B:4F:1A:B3:95:AB:B7:49:1F:44:49:E5:51:00:06:8A:FA:53:39:8BSHA256: 8A:73:D3:A5:73:B4:30:18:81:ED:60:2A:57:6A:2C:BF:50:07:8C:4C:C8:0B:CE:52:FF:F7:19:33:98:6B:7A:66
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3扩展:#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 07 8C E8 A0 26 83 A6 E8   5D C1 84 E7 C2 D4 45 8E  ....&...].....E.
0010: A4 D8 62 5A                                        ..bZ
]
]

使用JEB也可以查看相关信息:

该Fingerprint常用于各种第三方SDK平台的客户端身份验证(要求将该值上报到SDK平台,SDK中调接口获取)。

6.3.4 APP如何获得证书指纹(Fingerprint)

app通常需要获取证书指纹,以验证当前的app客户端是否被tampered了。

app中相关的java代码如下:

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES);SigningInfo signingInfo = packageInfo.signingInfo;signatures = signingInfo.getApkContentsSigners();} else {packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);signatures = packageInfo.signatures;}String signBase64 = Base64Util.encodeToString(signatures [0].toByteArray());nowSignMD5 = MD5Utils.MD5(signBase64);

7. 相关校验

7.1 App层面

7.1.1 Android拒绝安装没有证书的APK

通过命令行adb install安装一个没有签名的APK时,会提示INSTALL_PARSE_FAILED_NO_CERTIFICATES错误。

7.1.2 Android不校验证书的合法性

只要证书中公钥解密CERT.SF签名得到的CERT.SF摘要,和计算出的CERT.SF摘要相同,不管证书是不是合法的,Android都允许安装。

7.1.3 两个版本证书不一致时,APK升级失败

如果一个APK的前后两个版本证书不一致时,Android拒绝升级APK。

7.2 操作系统层面

7.2.1 Android中的系统签名

Android设计了四种不同类型的签名:platform, share, media和testkey,默认置于在源码的build/target/product/security目录下,分别用于给不同类型的系统应用进行签名。从Android Lollipop开始,Android还对boot.img和system.img进行签名以防被篡改,所以在原来四组签名的基础上又增加了verity。

build/target/product/security
├── (media.pk8, media.x509.pem)       #用于给MediaProvider, Gallery等签名
├── (platform.pk8, platform.x509.pem) #用于给Settings, Phone等签名
├── (shared.pk8, shared.x509.pem)     #用于给Launcher, Dailer等签名
├── (testkey.pk8, testkey.x509.pem)   #用于给一般应用签名
└── (verity.pk8, verity.x509.pem)     #用于给boot.img和system.img签名

.pk8为私钥, .509.pem为证书(包含公钥)。

7.2.2 根据签名界定权限

应用可以定义属于自己的permission,并为其设定protectionLevel,通过Android的权限授予机制,来防止API被滥用。
譬如在packages/apps/Launcer3/AndroidManifest.xml中,就定义了如下权限:

<permissionandroid:name="com.android.launcher3.permission.WRITE_SETTINGS"android:permissionGroup="android.permission-group.SYSTEM_TOOLS"android:protectionLevel="signatureOrSystem"android:label="@string/permlab_write_settings"android:description="@string/permdesc_write_settings"/>

注意android:protectionLevel="signatureOrSystem"
这就表明一个app要想获取com.android.launcher3.permission.WRITE_SETTINGS这个权限,app要么与Launcher3具有相同的签名(公私钥对),要么是一个系统应用。

有了数字签名,就相当于多了一种受信机制。两个不同的APK,签名相同,意味着来源相同,彼此是受信的。

7.2.3 SELinux根据签名给APK打标签

详细内容参考《Android数字签名机制和应用场景》

在SELinux环境下,所有的文件和进程都有标签(文件通过ls -Z命令,进程通过ps -Z命令可以查看),这个标签称为SELinux Context

  • 部分标签是事先定义好的,譬如system/sepolicy/file_contexts文件中定义了一些系统文件和目录的标签;
  • 部分标签是根据规则生成的,譬如在fork子进程时,会根据TE(Type Enforcement)文件中定义的规则,为子进程打上标签。
  1. Android基于签名为APK打标签。system/sepolicy/mac_permissions.xml中记录签名到SELinux标签的映射
  2. 当APK的应用进程启动时,根据seapp_contexts中定义的seinfo=>SELinux Context映射,设置进程的SELinux标签。

不同的标签对应着不同的可操作文件类型(例如system_app_data_file等)。

【Android安全】Android app开发者证书和代码签名机制相关推荐

  1. app内录屏开发 ios_盘点APP开发者喜爱iOS企业签名的原因

    相信很多APP开发者在做iOS签名的时候,最先接触的都会是iOS企业签名,因为App Store上架实在不容易,通过企业签名来完成APP分发这样的事情,可以说是一件美事.并且企业签名也是苹果官方默许的 ...

  2. 沃通开年采购季,SSL证书、代码签名证书特惠低价,助力保障关键数据安全

    近期<关键信息基础设施安全保护条例>.<网络安全审查办法>等一系列政策的实施,今年国家对网络数据安全将更为重视,如何构建网络安全体系.保障企业数据安全将会是今年众多企业的重点工 ...

  3. 关于VeriSign(威瑞信)_VeriSign(威瑞信)全球服务网络遍及全球,面向各地客户提供PKI及SSL证书、代码签名证书服务...

    VeriSign(威瑞信)公司成立于1995年,总部在美国加州山景城. 公司于1998年上市,是标普500指数之一.威瑞信公司提供的整套安全在线交易服务保障个人和公司放心从事数字交易活动.其中保护网站 ...

  4. 关于天威诚信数字认证中心_VeriSign在中国大陆区SSL证书和代码签名证书市场份额中有95%来自天威诚信...

    北京天威诚信电子商务服务有限公司(iTruschina)是经信息产业部批准的全国性PKI/CA企业,是专门从事数字信任服务.PKI/CA建设服务.PKI/CA应用服务.PKI/CA运营管理咨询服务和P ...

  5. Android打包混淆----APP加密防破解 + 重新签名

    ① 准备一个打包过的app文件包 . ②  登陆移动APP加密防破解爱加密官网http://www.ijiami.cn,没有账号的需要先注册账号(登陆后才能上传App文件进行加密). ③ 注册完后,登 ...

  6. linux安装globalsign证书,globalsign代码签名证书

    GlobalSign代码签名证书被平台上的开发人员使用来对通过Internet 分发的应用程序和软件进行数字签名. 因为签名的代码包括发布者的名称以及该代码自发布以来未被篡改的保证,任何人从互联网下载 ...

  7. 代码签名证书_代码签名

    代码签名证书 介绍: 建议将MS Office应用程序中的"宏安全级别"设置为"高". 除非与项目关联的任何VBA代码都已签名(带有证书),否则它将停止运行. ...

  8. Windows系统openssl颁发根证书以及下签子证书和代码签名证书

    此文章转载自我的博客GoodBoyboy 1.首先创建根证书 (1)生成私钥 openssl genrsa -aes256 -out root.key 2048 然后输入私钥密码 生成root.key ...

  9. Android打包混淆----APP加密防破解 + 重新签名

    ~ ~  APP加密(混淆打包防反编译)的步骤:~ ~ ① 准备一个打包过的app文件包 . ②  登陆移动APP加密防破解爱加密官网http://www.ijiami.cn,没有账号的需要先注册账号 ...

最新文章

  1. LeetCode刷题记录2——217. Contains Duplicate(easy)
  2. Scala使用半生对象来创建伴生类对象(默认单例)
  3. SAP BSP - how to access javascript file via Mime API
  4. W ndoWs文件夹窗口,如何在本地网络中访问-Synology-NAS-上的文件-(Wndows).pdf
  5. GdiPlus[30]: IGPPen: 线帽
  6. java基础代码下载_Java基础(一)(示例代码)
  7. AC自动机:例题与机制详解
  8. 如何实现动态水球图 --》 echars结合echarts-liquidfill实现
  9. Juventas, the Roman Goddess of Youth [ Juventas, 罗马青春女神]
  10. 浏览器播放rtsp视频流方案(ffmpeg + nginx转m3u8)
  11. windowbuilder安装
  12. mysql启动失败2005_数据库2005服务启动不了
  13. Android Studio 第一个JNI程序
  14. 2018只剩32天,动着心思想跳槽的你,还要YY到什么时候
  15. cad转pdf格式简易步骤
  16. python+nodejs+Vue体检信息管理系统项目源码
  17. kubeedge解决边端keadm join的时候卡住的问题
  18. linux 修改文件的权限
  19. 删除Linux Terminal中的历史记录
  20. iOS开发-dispatch_once相关

热门文章

  1. python批量处理应用
  2. 光电编码器的原理及应用场合_增量式光电编码器的构造和原理及应用
  3. 亚马逊宣布与西云数据达成合作,旨在进一步扩大中国业务
  4. 从火星传图有多难-业余眼光看深空通信
  5. 大数据如何使用Python分析微信数据
  6. 20201206英语单词学习(仅供自己记录)
  7. android开发笔记之系统属性(ro.com.google.clientidbase.ms)随卡适配
  8. macOS下载安装Java步骤
  9. bland c++_为什么要使用bland altman图进行ab测试python代码
  10. 人工智能的利弊及如何做能最安全的培养人工智能