Android签名机制之—签名进程详解-Android-优质IT资源分享社区

admin
管理员
管理员
  • UID1
  • 粉丝33
  • 关注4
  • 发帖数581
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:296回复:0

  Android签名机制之—签名进程详解

楼主#
更多 发布于:2016-05-13 14:54


一、前言
又是过了好长时间,没写文章的双手都有点难受了。今日是圣诞节,仍是得上班。由于前几天有一个之前的搭档,在请求微信SDK的时分,遇到签名的疑问,问了我一下,成果把我难倒了。。我说Android中的签名咱们都会了解的,即是为了安全,不让他人修正你的apk,可是咱们真实的有了解多少呢?所以预备两篇文章好好介绍一下Android中签名机制。
在说道Android签名之前,咱们需求了解的几个常识点
1、数据摘要(数据指纹)、签名文件,证书文件
2、jarsign东西签名和signapk东西签名
3、keystore文件和pk8文件,x509.pem文件的联络
4、怎么手动的签名apk
上面介绍的四个常识点,即是今日介绍的中心,咱们来逐个看这些疑问。
二、预备常识
首要来看一下数据摘要,签名文件,证书文件的常识点
1、数据摘要
这个常识点极好了解,baidu百科即可,本来他也是一种算法,即是对一个数据源进行一个算法今后得到一个摘要,也叫作数据指纹,不相同的数据源,数据指纹一定不相同,就和人相同。
音讯摘要算法(Message Digest Algorithm)是一种能发作特殊输出格局的算法,其原理是依据一定的运算规矩对初始数据进行某种形式的信息获取,被获取出的信息就被称作初始数据的音讯摘要。
闻名的摘要算法有RSA公司的MD5算法和SHA-1算法及其许多的变体。
音讯摘要的主要特点有:
1)不管输入的音讯有多长,核算出来的音讯摘要的长度老是固定的。例如运用MD5算法摘要的音讯有128个比特位,用SHA-1算法摘要的音讯最终有160比特位的输出。
2)通常来说(不考虑磕碰的情况下),只需输入的初始数据不相同,对其进行摘要今后发作的音讯摘要也必不相同,即便初始数据稍有改动,输出的音讯摘要便彻底不相同。可是,相同的输入必会发作相同的输出。
3)具有不行逆性,即只能进行正向的信息摘要,而无法从摘要中康复出任何的初始音讯。
2、签名文件和证书
签名文件和证书是成对呈现了,二者不行别离,并且咱们后边经过源码能够看到,这两个文件的姓名也是相同的,仅仅后缀名不相同。
本来数字签名的概念很简单。咱们知道,要确保牢靠通讯,有必要要处理两个疑问:首要,要确定音讯的来历确实是其申明的那个人;其次,要确保信息在传递的进程中不被第三方篡改,即便被篡改了,也能够发觉出来。
所谓数字签名,即是为了处理这两个疑问而发作的,它是对前面说到的非对称加密技能与数字摘要技能的一个具体的运用。
对于音讯的发送者来说,先要生成一对公私钥对,将公钥给音讯的接收者。
假如音讯的发送者有一天想给音讯接收者发音讯,在发送的信息中,除了要包括初始的音讯外,还要加上别的一段音讯。这段音讯经过如下两步生成:
1)对要发送的初始音讯获取音讯摘要;
2)对获取的信息摘要用自个的私钥加密。
经过这两步得出的音讯,即是所谓的初始信息的数字签名。
而对于信息的接收者来说,他所收到的信息,将包括两个有些,一是初始的音讯内容,二是附加的那段数字签名。他将经过以下三步来验证音讯的真伪:
1)对初始音讯有些获取音讯摘要,留意这儿运用的音讯摘要算法要和发送方运用的共同;
2)对附加上的那段数字签名,运用预先得到的公钥解密;
3)比较前两步所得到的两段音讯是不是共同。假如共同,则标明音讯确实是希望的发送者发的,且内容没有被篡改正;相反,假如不共同,则标明传送的进程中一定出了疑问,音讯不行信。
经过这种所谓的数字签名技能,确实能够有用处理牢靠通讯的疑问。假如初始音讯在传送的进程中被篡改了,那么在音讯接收者那里,对被篡改的音讯获取的摘要一定和初始的不相同。并且,由于篡改者没有音讯发送方的私钥,即便他能够从头算出被篡改音讯的摘要,也不能假造出数字签名。
所以,综上所述,数字签名本来即是只需信息的发送者才干发作的他人无法假造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有用证实。
不知道咱们有没有留意,前面讲的这种数字签名办法,有一个条件,即是音讯的接收者有必要要事前得到准确的公钥。假如一开始公钥就被他人篡改了,那坏人就会被你当成好人,而真实的音讯发送者给你发的音讯会被你视作无效的。并且,许多时分根本就不具有事前交流公钥的信息通道。那么怎么确保公钥的安全可信呢?这就要靠数字证书来处理了。
所谓数字证书,通常包括以下一些内容:
证书的发布组织(Issuer)
证书的有用期(Validity)
音讯发送方的公钥
证书一切者(Subject)
数字签名所运用的算法
数字签名
能够看出,数字证书本来也用到了数字签名技能。只不过要签名的内容是音讯发送方的公钥,以及一些其它信息。但与通常数字签名不相同的是,数字证书中签名者不是马马虎虎一个通常的组织,而是要有一定公信力的组织。这就如同你的大学毕业证书上签名的通常都是德高望重的校长相同。通常来说,这些有公信力组织的根证书已经在设备出厂前预先装置到了你的设备上了。所以,数字证书能够确保数字证书里的公钥确实是这个证书的一切者的,或许证书能够用来承认对方的身份。数字证书主要是用来处理公钥的安全发放疑问。
综上所述,总结一下,数字签名和签名验证的大体流程如下图所示:


3、jarsign和signapk东西
了解到完了签名中的三个文件的常识点今后,下面持续来看看Android中签名的两个东西:jarsign和signapk
对于这两个东西开始的时分很简单混杂,感受他们两到底有啥差异吗?
本来这两个东西极好了解,jarsign是Java本生自带的一个东西,他能够对jar进行签名的。而signapk是后边专门为了Android运用程序apk进行签名的东西,他们两的签名算法没啥差异,主要是签名时运用的文件不相同,这个就要引出第三个疑问了。
4、keystore文件和pk8,x509.pem文件的差异
咱们上面了解到了jarsign和signapk两个东西都能够进行Android中的签名,那么他们的差异在于签名时运用的文件不相同
jarsign东西签名时运用的是keystore文件
signapk东西签名时运用的是pk8,x509.pem文件
其间咱们在运用Eclipse东西写程序的时分,出Debug包的时分,默许用的是jarsign东西进行签名的,并且Eclipse中有一个默许签名文件:


咱们能够看到这个默许签名的keystore文件,当然咱们能够选择咱们自个指定的keystore文件。
这儿还有一个常识点:
咱们看到上面有MD5和SHA1的摘要,这个即是keystore文件中私钥的数据摘要,这个信息也是咱们在请求许多开发渠道账号的时分需求填入的信息,比方请求baidu地图,微信SDK等,会需求填写运用的MD5或许是SHA1信息。
5、手动的签名Apk包
1》运用keytool和jarsigner来进行签名
当然,咱们在正式签名处release包的时分,咱们需求创立一个自个的keystore文件:




这儿咱们能够对keystore文件起自个的姓名,并且后缀名也是无关紧要的。创立完文件今后,也会生成MD5和SHA1的值,这个值能够不必记载的,能够经过指令检查keystore文件的MD5和SHA1的值。
keytool -list -keystore debug.keystore


当然咱们都知道这个keytstore文件的主要性,说白了就相当于你的银行卡暗码。你懂得。
这儿咱们看到用Eclipse主动签名和生成一个keystore文件,咱们也能够运用keytool东西生成一个keystore文件。这个办法网上有,这儿就不做太多的介绍了。然后咱们能够运用jarsign来对apk包进行签名了。
咱们能够手动的生成一个keystore文件:
keytool -genkeypair -v -keyalg DSA -keysize 1024 -sigalg SHA1withDSA -validity 20000 -keystore D:\jiangwei.keystore -alias jiangwei -keypass jiangwei -storepass jiangwei


这个指令有点长,有几个主要的参数需求阐明:
-alias是界说别号,这儿为debug
-keyalg是规则签名算法,这儿是DSA,这儿的算法直接联络到后边apk中签名文件的后缀名,到后边会具体阐明
在用jarsigner东西进行签名
jarsigner -verbose -sigalg SHA1withDSA -digestalg SHA1 -keystore D:\jiangwei.keystore -storepass jiangwei D:\123.apk jiangwei


这么咱们就成功的对apk进行签名了。
签名的进程中遇到的疑问:
1》证书链找不到的疑问


这个是由于最终一个参数alias,是keystore的别号输错了。
2》生成keystore文件的时分提示暗码过错


这个因素是由于在当时目录已经有debug.ketystore了,在生成一个debug.keystore的话,就会报错
3》找不到别号的疑问


这个疑问的因素是由于咱们在运用keytool生成keystore的时分,起了debug的别号,这个疑问困惑了我好久,最终做了许多比如才发现的,即是只需咱们的keystore文件的别号是debug的话,就会报这么的过错。这个应当和体系默许的签名debug.keystore中的别号是debug有联络吧?没有找到jarsigner的源码,所以只能猜测了,可是这三个疑问在这儿标示一下,以防今后在遇到。
留意:Android中是答应运用多个keystore对apk进行签名的,这儿我就不在粘贴指令了,我又创立了几个keystore对apk进行签名:


这儿我把签名今后的apk进行解压今后,发现有三个签名文件和证书(.SF/.DSA)
这儿我也能够留意到,咱们签名时用的是DSA算法,这儿的文件后缀名即是DSA
并且文件名是keystore的别号
哎,这儿算是理明白了咱们上面的怎么运用keytool发作keystore以及,用jarsigner来进行签名。
2》运用signapk来进行签名
下面咱们再来看看signapk东西进行签名:
java -jar signapk.jar .testkey.x509.pem testkey.pk8 debug.apk debug.sig.apk
这儿需求两个文件:.pk8和.x509.pem这两个文件
pk8是私钥文件
x509.pem是富含公钥的文件
这儿签名的话就不在演示了,这儿没啥疑问的。
可是这儿需求留意的是:signapk签名今后的apk中的META-INF文件夹中的三个文件的姓名是这么的,由于signapk在前面的时分不像jarsigner会主动运用别号来命名文件,这儿即是写死了是CERT的姓名,不过文件名不影响的,后边剖析Android中的Apk校验进程中会说道,只会经过后缀名来查找文件。


3》两种的签名办法有啥差异
那么疑问来了,jarsigner签名时用的是keystore文件,signapk签名时用的是pk8和x509.pem文件,并且都是给apk进行签名的,那么keystore文件和pk8,x509.pem他们之间是不是有啥联络呢?答案是一定的,网上搜了一下,公然他们之间是能够转化的,这儿就不在剖析怎么进行转化的,网上的比如貌似许多,有专门的的东西能够进行转化:


那么到这儿咱们就弄明白了这两个签名东西的差异和联络。
三、剖析Android中签名流程机制
下面咱们开始从源码的视点去看看Android中的签名机制和原理流程
由于网上没有找到jarsigner的源码,可是找到了signapk的源码,那么下面咱们就来看看signapk的源码吧:
源码方位:com/android/signapk/sign.java
经过上面的签名时咱们能够看到,Android签名apk今后,会有一个META-INF文件夹,这儿有三个文件:
MANIFEST.MF
CERT.RSA
CERT.SF
下面来看看这三个文件到底是干啥的?
1、MANIFEST.MF


咱们来看看源码:
public static void main(String[] args) {
if (args.length != 4) {
System.err.println("Usage: signapk " + "publickey.x509[.pem] privatekey.pk8 " + "input.jar output.jar");
System.exit(2);
}
JarFile inputJar = null;
JarOutputStream outputJar = null;
try {
X509Certificate publicKey = readPublicKey(new File(args[0]));
// Assume the certificate is valid for at least an hour.
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
PrivateKey privateKey = readPrivateKey(new File(args[1]));
inputJar = new JarFile(new File(args[2]), false); // Don't verify.
outputJar = new JarOutputStream(new FileOutputStream(args[3]));
outputJar.setLevel(9);
JarEntry je;
// MANIFEST.MF
Manifest manifest = addDigestsToManifest(inputJar);
je = new JarEntry(JarFile.MANIFEST_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
manifest.write(outputJar);
// CERT.SF
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
je = new JarEntry(CERT_SF_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureFile(manifest, new SignatureOutputStream(outputJar, signature));
// CERT.RSA
je = new JarEntry(CERT_RSA_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureBlock(signature, publicKey, outputJar);
// Everything else
copyFiles(manifest, inputJar, outputJar, timestamp);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
} finally {
try {
if (inputJar != null) inputJar.close();
if (outputJar != null) outputJar.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}
在main函数中,咱们看到需求输入四个参数,然后就做了三件事:
写MANIFEST.MF
//MANIFEST.MF
Manifest manifest = addDigestsToManifest(inputJar);
je = new JarEntry(JarFile.MANIFEST_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
manifest.write(outputJar);
在进入办法看看:
/** Add the SHA1 of every file to the manifest, creating it if necessary. */
private static Manifest addDigestsToManifest(JarFile jar) throws IOException, GeneralSecurityException {
Manifest input = jar.getManifest();
Manifest output = new Manifest();
Attributes main = output.getMainAttributes();
if (input != null) {
main.putAll(input.getMainAttributes());
} else {
main.putValue("Manifest-Version", "1.0");
main.putValue("Created-By", "1.0 (Android SignApk)");
}
BASE64Encoder base64 = new BASE64Encoder();
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] buffer = new byte[4096];
int num;
// We sort the input entries by name, and add them to the
// output manifest in sorted order. We expect that the output
// map will be deterministic.
TreeMap byName = new TreeMap();
for (Enumeration e = jar.entries(); e.hasMoreElements(); ) {
JarEntry entry = e.nextElement();
byName.put(entry.getName(), entry);
}
for (JarEntry entry: byName.values()) {
String name = entry.getName();
if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) && !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) && (stripPattern == null || !stripPattern.matcher(name).matches())) {
InputStream data = jar.getInputStream(entry);
while ((num = data.read(buffer)) > 0) {
md.update(buffer, 0, num);
}
Attributes attr = null;
if (input != null) attr = input.getAttributes(name);
attr = attr != null ? new Attributes(attr) : new Attributes();
attr.putValue("SHA1-Digest", base64.encode(md.digest()));
output.getEntries().put(name, attr);
}
}
return output;
}
代码逻辑仍是很简单的,主要看那个循环的意思:
除了三个文件(MANIFEST.MF,CERT.RSA,CERT.SF),别的的文件都会对文件内容做一次SHA1算法,即是核算出文件的摘要信息,然后用Base64进行编码即可,下面咱们用东西来做个事例看看是不是这么:
首要装置东西:HashTab
下载地址:http://www.baidu.com/s?wd=hashtab&rsv_spt=1&issp=1&f=8&rsv_bp=0&ie=utf-8&tn=baiduhome_pg&bs=hashtable
然后还有一个网站即是在线核算Base64:http://tomeko.net/online_tools/hex_to_base64.php?lang=en
那下面就开始咱们的验证作业吧:
咱们就来验证一下AndroidManifest.xml文件,首要在MANIFEST.MF文件中找到这个条目,记载SHA1的值


然后咱们装置HashTab今后,找到AndroidManifest.xml文件,右击,选择Hashtab:


复制SHA-1的值:9C64812DE7373B201C294101473636A3697FD73C,到上面的那个Base64转化网站,转化一下:


nGSBLec3OyAcKUEBRzY2o2l/1zw=
和MANIFEST.MF中的条目内容一模相同啦啦
那么从上面的剖析咱们就知道了,本来MANIFEST.MF中存储的是:
逐个遍历里边的一切条目,假如是目录就越过,假如是一个文件,就用SHA1(或许SHA256)音讯摘要算法获取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”特点的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”特点,其值即是该文件在apk包中的途径。
2、下面再来看一下CERT.SF文件内容


这儿的内容感受和MANIFEST.MF的内容差不多,来看看代码吧:
//CERT.SF
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
je = new JarEntry(CERT_SF_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureFile(manifest,new SignatureOutputStream(outputJar, signature));
进入到writeSignatureFile办法中:
/** Write a .SF file with a digest the specified manifest. */
private static void writeSignatureFile(Manifest manifest, OutputStream out) throws IOException, GeneralSecurityException {
Manifest sf = new Manifest();
Attributes main = sf.getMainAttributes();
main.putValue("Signature-Version", "1.0");
main.putValue("Created-By", "1.0 (Android SignApk)");
BASE64Encoder base64 = new BASE64Encoder();
MessageDigest md = MessageDigest.getInstance("SHA1");
PrintStream print = new PrintStream( new DigestOutputStream(new ByteArrayOutputStream(), md),
true, "UTF-8");
// Digest of the entire manifest
manifest.write(print);
print.flush();
main.putValue("SHA1-Digest-Manifest", base64.encode(md.digest()));
Map entries = manifest.getEntries();
for (Map.Entry entry : entries.entrySet()) {
// Digest of the manifest stanza for this entry.
print.print("Name: " + entry.getKey() + "\r\n");
for (Map.Entry att : entry.getValue().entrySet()) {
print.print(att.getKey() + ": " + att.getValue() + "\r\n");
}
print.print("\r\n");
print.flush();
Attributes sfAttr = new Attributes();
sfAttr.putValue("SHA1-Digest", base64.encode(md.digest()));
sf.getEntries().put(entry.getKey(), sfAttr);
}
sf.write(out);
}
首要咱们能够看到,需求对之前的MANIFEST.MF文件全部内容做一个SHA1放到SHA1-Digest-Manifest字段中:


咱们看看收支的manifest变量即是刚刚写入了MANIFEST.MF文件的


这个咱们能够验证一下:


然后转化一下


看到了吧,和文件中的值是相同的啦啦


下面咱们持续看代码,有一个循环:
Map entries = manifest.getEntries();
for (Map.Entry entry : entries.entrySet()) {
// Digest of the manifest stanza for this entry.
print.print("Name: " + entry.getKey() + "\r\n");
for (Map.Entry att : entry.getValue().entrySet()) {
print.print(att.getKey() + ": " + att.getValue() + "\r\n");
}
print.print("\r\n");
print.flush();
Attributes sfAttr = new Attributes();
sfAttr.putValue("SHA1-Digest", base64.encode(md.digest()));
sf.getEntries().put(entry.getKey(), sfAttr);
}
sf.write(out);
这儿仍是用到了刚刚传入的mainfest变量,遍历他的条目内容,然后进行SHA算法核算在Base64一下:
本来即是对MANIFEST.MF文件中的每个条目内容做一次SHA,在保留一下即可,做个比如验证一下:
用AndroidManifest.xml为例,咱们把MANIFEST.MF文件中的条目拷贝保留到txt文档中:


这儿需求留意的是,咱们保留今后,需求增加两个换行,咱们能够在代码中看到逻辑:


然后咱们核算txt文档的SHA值:




看到了吧,这儿核算的值是相同的啦啦


到这儿咱们就知道CERT.SF文件做了啥:
1》核算这个MANIFEST.MF文件的全体SHA1值,再经过BASE64编码后,记载在CERT.SF主特点块(在文件头上)的“SHA1-Digest-Manifest”特点值值下
2》逐条核算MANIFEST.MF文件中每一个块的SHA1,并经过BASE64编码后,记载在CERT.SF中的同名块中,特点的姓名是“SHA1-Digest
3、最终咱们在来看一下CERT.RSA文件


这儿咱们看到的都是二进制文件,由于RSA文件加密了,所以咱们需求用openssl指令才干检查其内容
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs –text


对于这些信息,能够看下面这张图:

[img]http://img.blog.csdn.net/20151225163015075?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center[/img]
咱们来看一下代码:
/** Write a .RSA file with a digital signature. */
private static void writeSignatureBlock(Signature signature, X509Certificate publicKey, OutputStream out) throws IOException, GeneralSecurityException {
SignerInfo signerInfo = new SignerInfo(new X500Name(publicKey.getIssuerX500Principal().getName()),
publicKey.getSerialNumber(),
AlgorithmId.get("SHA1"),
AlgorithmId.get("RSA"),
signature.sign());
PKCS7 pkcs7 = new PKCS7(
new AlgorithmId[] { AlgorithmId.get("SHA1") },
new ContentInfo(ContentInfo.DATA_OID, null),
new X509Certificate[] { publicKey },
new SignerInfo[] { signerInfo });
pkcs7.encodeSignedData(out);
}
咱们看到,这儿会把之前生成的 CERT.SF文件, 用私钥核算出签名, 然后将签名以及包括公钥信息的数字证书一起写入 CERT.RSA 中保留。CERT.RSA是一个满足PKCS7格局的文件。
四、为何要这么来签名
上面咱们就介绍了签名apk今后的三个文件的具体内容,那么下面来总结一下,Android中为何要用这种办法进行加密签名,这种方加密是不是最安全的呢?下面咱们来剖析一下,假如apk文件被篡改后会发作啥。
首要,假如你改动了apk包中的任何文件,那么在apk装置校验时,改动后的文件摘要信息与MANIFEST.MF的查验信息不相同,于是验证失利,程序就不能成功装置。
其次,假如你对更改的过的文件相应的算出新的摘要值,然后更改MANIFEST.MF文件里边对应的特点值,那么一定与CERT.SF文件中算出的摘要值不相同,照样验证失利。
最终,假如你还不死心,持续核算MANIFEST.MF的摘要值,相应的更改CERT.SF里边的值,那么数字签名值一定与CERT.RSA文件中记载的不相同,仍是失利。
那么能不能持续假造数字签名呢?不行能,由于没有数字证书对应的私钥。
所以,假如要从头打包后的运用程序能再Android设备上装置,有必要对其进行重签名。
从上面的剖析能够得出,只需修正了Apk中的任何内容,就有必要从头签名,不然会提示装置失利,当然这儿不会剖析,后边一篇文章会注重剖析为何会提示装置失利。
五、常识点整理
1、数据指纹,签名文件,证书文件的意义
1》数据指纹即是对一个数据源做SHA/MD5算法,这个值是仅有的
2》签名文件技能即是:数据指纹+RSA算法
3》证书文件中包括了公钥信息和别的信息
4》在Android签名今后,其间SF即是签名文件,RSA即是证书文件咱们能够运用openssl来检查RSA文件中的证书信息和公钥信息
2、咱们了解了Android中的签名有两种办法:jarsigner和signapk 这两种办法的差异是:
1》jarsigner签名时,需求的是keystore文件,而signapk签名的时分是pk8,x509.pem文件
2》jarsigner签名今后的SF和RSA文件名默许是keystore的别号,而signapk签名今后文件名是固定的:CERT
3》Eclipse中咱们在跑Debug程序的时分,默许用的是jarsigner办法签名的,用的也是体系默许的debug.keystore签名文件
4》keystore文件和pk8,x509.pem文件之间能够互相转化
六、考虑
咱们在剖析了签名技能今后,无意中发现一个疑问,即是CERT.SF,MANIFEST.MF,这两个文件中的内容的name字段都是apk中的资本名,那么就有一个疑问了,假如资本名很长,并且apk中的资本许多,那么这两个文件就会很大,那么这儿咱们是不是能够优化呢?后边在剖析怎么减小apk大小的文章中会持续解说,这儿先提出这个疑问。

[img]http://img.blog.csdn.net/20151225151920791?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center[/img]
资本下载:http://download.csdn.net/detail/jiangwei0910410003/9377046
总结
上面咱们就经过源码来介绍了Android中的签名进程,全部进程仍是很明白的,文章写得有点长,假如咱们看的有疑问的话,记住给我留言,后边我还会再写一篇姊妹篇文章:Android中的签名校验进程详解,等待中~~






优质IT资源分享社区为你提供此文。
本站有大量优质android教程视频,资料等资源,包含android基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。

android教程视频
优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客