安卓证书相关验证机制:
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
对待发送的数据明文进行Hash,通常可采用MD5或SHA算法,然后采用私钥对Hash值进行加密,得到签名。将数据明文和签名一同发送出去。
(为什么要先对原始数据进行Hash后再用私钥加密呢?因为原数据可能比较大,直接使用私钥加密将会非常耗时。)
接收数据以后,会经过签名验证,其实就是比较两个Hash值:采用同样的Hash算法对数据明文进行哈希,得到一个Hash值;采用公钥对签名进行解密后,得到另一个Hash值。如果两个Hash值相同,则说明数据没有被篡改而且来源可信
keytool是JDK的一个工具,用于密钥和证书的管理。
keytool的主要操作对象是keystore文件,该文件一般以.keystore或.jks(Java KeyStore)为后缀名。
keystore可以存储多个密钥对(Key Pair),每一个密钥对包含私钥(Private Key)和多个证书(Certificate):
证书就是对公钥再次私钥签名产生的结果。证书中保存着被签名的公钥和签名。
上述证书的生成过程会导致一个无限的链条:要得到证书,就需要对公钥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),其实多个证书的结构就是证书链。
如果将keystore看做密钥和证书管理的数据库,那么keytool就是这个数据库增、删、改、查的接口。
应用层面:Android对APK的签名要求
Android拒绝安装没有签名的APK
Android并不校验证书的合法性(这与https网站证书不一样,https网站证书是要校验签发者的合法性的)
当签名不匹配时,APK升级会失败
系统层面:Android基于数字签名的一些机制
编译Android系统时,会根据不同应用的类型进行签名
Android基于数字签名来判定是否给应用授权
Android基于数字签名来标记APK的SELinux Lable
给定一个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并不是一个单纯的证书。
MANIFEST.MF:记录了APK中每一个文件的摘要
Manifest-Version: 1.0
Built-By: Generated-by-ADT
Created-By: Android Gradle 3.4.2
Name: 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=
…………
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: 2
Name: 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相同。
CERT.RSA:主要内容是对CERT.SF的私钥A签名(对CERT.SF的摘要的私钥A加密) 和 证书(用于保存公钥A) 。RSA后缀表示签名是基于RSA算法生成的。
证书的本质作用是保存公钥A。同时,证书具备可验证性(在某些额外信息被获取的情况下,用户可以判定证书是否是合法的)。
注意,CERT.RSA是三者中唯一用到私钥的。
证书保存了:{公钥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: sha256WithRSAEncryption
Issuer: C=CN
Validity
Not Before: Dec 20 04:41:56 2018 GMT
Not After : Dec 14 04:41:56 2043 GMT
Subject: C=CN
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-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:2f
Exponent: 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:5A
Signature Algorithm: sha256WithRSAEncryption
Signature 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签名结果,用于验证证书的可信性,这里暂时不涉及。
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-----
使用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-signedData
15: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 :01
26: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 :sha256
41: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-data
56: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 :02
73:d=6 hl=2 l= 4 prim: INTEGER :01FFE8FE
79:d=6 hl=2 l= 13 cons: SEQUENCE
81:d=7 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
92: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 :countryName
105:d=9 hl=2 l= 2 prim: PRINTABLESTRING :CN
109:d=6 hl=2 l= 30 cons: SEQUENCE
111:d=7 hl=2 l= 13 prim: UTCTIME :181220044156Z
126:d=7 hl=2 l= 13 prim: UTCTIME :431214044156Z
141: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 :countryName
152:d=9 hl=2 l= 2 prim: PRINTABLESTRING :CN
156: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 :rsaEncryption
173: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...c
0020 - 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.(;`......<$gG
0040 - 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......U9d
0070 - 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.......}.....8
00a0 - 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.......5
00f0 - 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 Identifier
461: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...bZ
485:d=5 hl=2 l= 13 cons: SEQUENCE
487:d=6 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
498: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.....l
0040 - 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......$kH
0070 - 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.K
00e0 - 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 G
761: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 :01
772: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 :countryName
785:d=9 hl=2 l= 2 prim: PRINTABLESTRING :CN
789:d=6 hl=2 l= 4 prim: INTEGER :01FFE8FE
795:d=5 hl=2 l= 13 cons: SEQUENCE
797:d=6 hl=2 l= 9 prim: OBJECT :sha256
808: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 :rsaEncryption
823: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.......V
0010 - 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.D
0030 - 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/.....+).n
0050 - 9d 4e 96 e2 03 0c df af-9a b4 bb fd a8 9c f7 39 .N.............9
0060 - 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 [email protected].....
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..Z
00e0 - 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摘要
证书指纹是对证书的哈希值。
使用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:8B
SHA256: 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中调接口获取)。
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);
通过命令行adb install安装一个没有签名的APK时,会提示INSTALL_PARSE_FAILED_NO_CERTIFICATES
错误。
只要证书中公钥解密CERT.SF签名得到的CERT.SF摘要,和计算出的CERT.SF摘要相同,不管证书是不是合法的,Android都允许安装。
如果一个APK的前后两个版本证书不一致时,Android拒绝升级APK。
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为证书(包含公钥)。
应用可以定义属于自己的permission,并为其设定protectionLevel,通过Android的权限授予机制,来防止API被滥用。
譬如在packages/apps/Launcer3/AndroidManifest.xml中,就定义了如下权限:
<permission
android: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,签名相同,意味着来源相同,彼此是受信的。
详细内容参考《Android数字签名机制和应用场景》
在SELinux环境下,所有的文件和进程都有标签(文件通过ls -Z
命令,进程通过ps -Z
命令可以查看),这个标签称为SELinux Context。
system/sepolicy/mac_permissions.xml
中记录签名到SELinux标签的映射。不同的标签对应着不同的可操作文件类型(例如system_app_data_file
等)。