Android簽名機制之---簽名過程詳解

1、前言

又是過了好長時間,沒寫文章的雙手都有點難受了。今天是聖誕節,仍是得上班。由於前幾天有一個以前的同事,在申請微信SDK的時候,遇到簽名的問題,問了我一下,結果把我難倒了。。我說Android中的簽名你們都會熟悉的,就是爲了安全,不讓別人修改你的apk,可是咱們真正的有了解多少呢?因此準備兩篇文章好好介紹一下Android中籤名機制。php

在說道Android簽名以前,咱們須要瞭解的幾個知識點java

一、數據摘要(數據指紋)、簽名文件,證書文件android

二、jarsign工具簽名和signapk工具簽名git

三、keystore文件和pk8文件,x509.pem文件的關係算法

四、如何手動的簽名apk安全

上面介紹的四個知識點,就是今天介紹的核心,咱們來一一看這些問題。微信


2、準備知識

首先來看一下數據摘要,簽名文件,證書文件的知識點函數

一、數據摘要

這個知識點很好理解,百度百科便可,其實他也是一種算法,就是對一個數據源進行一個算法以後獲得一個摘要,也叫做數據指紋,不一樣的數據源,數據指紋確定不同,就和人同樣。工具

消息摘要算法(Message Digest Algorithm)是一種能產生特殊輸出格式的算法,其原理是根據必定的運算規則對原始數據進行某種形式的信息提取,被提取出的信息就被稱做原始數據的消息摘要。
著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的變體。
消息摘要的主要特色有:
1)不管輸入的消息有多長,計算出來的消息摘要的長度老是固定的。例如應用MD5算法摘要的消息有128個比特位,用SHA-1算法摘要的消息最終有160比特位的輸出。
2)通常來講(不考慮碰撞的狀況下),只要輸入的原始數據不一樣,對其進行摘要之後產生的消息摘要也必不相同,即便原始數據稍有改變,輸出的消息摘要便徹底不一樣。可是,相同的輸入必會產生相同的輸出。
3)具備不可逆性,即只能進行正向的信息摘要,而沒法從摘要中恢復出任何的原始消息。
優化


二、簽名文件和證書

簽名文件和證書是成對出現了,兩者不可分離,並且咱們後面經過源碼能夠看到,這兩個文件的名字也是同樣的,只是後綴名不同。

其實數字簽名的概念很簡單。你們知道,要確保可靠通訊,必需要解決兩個問題:首先,要肯定消息的來源確實是其申明的那我的;其次,要保證信息在傳遞的過程當中不被第三方篡改,即便被篡改了,也能夠發覺出來。
所謂數字簽名,就是爲了解決這兩個問題而產生的,它是對前面提到的非對稱加密技術與數字摘要技術的一個具體的應用。
對於消息的發送者來講,先要生成一對公私鑰對,將公鑰給消息的接收者。
若是消息的發送者有一天想給消息接收者發消息,在發送的信息中,除了要包含原始的消息外,還要加上另一段消息。這段消息經過以下兩步生成:
1)對要發送的原始消息提取消息摘要;
2)對提取的信息摘要用本身的私鑰加密。
經過這兩步得出的消息,就是所謂的原始信息的數字簽名。
而對於信息的接收者來講,他所收到的信息,將包含兩個部分,一是原始的消息內容,二是附加的那段數字簽名。他將經過如下三步來驗證消息的真僞:
1)對原始消息部分提取消息摘要,注意這裏使用的消息摘要算法要和發送方使用的一致;
2)對附加上的那段數字簽名,使用預先獲得的公鑰解密;
3)比較前兩步所獲得的兩段消息是否一致。若是一致,則代表消息確實是指望的發送者發的,且內容沒有被篡改過;相反,若是不一致,則代表傳送的過程當中必定出了問題,消息不可信。
經過這種所謂的數字簽名技術,確實能夠有效解決可靠通訊的問題。若是原始消息在傳送的過程當中被篡改了,那麼在消息接收者那裏,對被篡改的消息提取的摘要確定和原始的不同。而且,因爲篡改者沒有消息發送方的私鑰,即便他能夠從新算出被篡改消息的摘要,也不能僞造出數字簽名。
因此,綜上所述,數字簽名其實就是隻有信息的發送者才能產生的別人沒法僞造的一段數字串,這段數字串同時也是對信息的發送者發送信息真實性的一個有效證實。
不知道你們有沒有注意,前面講的這種數字簽名方法,有一個前提,就是消息的接收者必需要事先獲得正確的公鑰。若是一開始公鑰就被別人篡改了,那壞人就會被你當成好人,而真正的消息發送者給你發的消息會被你視做無效的。並且,不少時候根本就不具有事先溝通公鑰的信息通道。那麼如何保證公鑰的安全可信呢?這就要靠數字證書來解決了。
所謂數字證書,通常包含如下一些內容:
證書的發佈機構(Issuer)
證書的有效期(Validity)
消息發送方的公鑰
證書全部者(Subject)
數字簽名所使用的算法
數字簽名
能夠看出,數字證書其實也用到了數字簽名技術。只不過要簽名的內容是消息發送方的公鑰,以及一些其它信息。但與普通數字簽名不一樣的是,數字證書中籤名者不是隨隨便便一個普通的機構,而是要有必定公信力的機構。這就好像你的大學畢業證書上簽名的通常都是德高望重的校長同樣。通常來講,這些有公信力機構的根證書已經在設備出廠前預先安裝到了你的設備上了。因此,數字證書能夠保證數字證書裏的公鑰確實是這個證書的全部者的,或者證書能夠用來確認對方的身份。數字證書主要是用來解決公鑰的安全發放問題。
綜上所述,總結一下,數字簽名和簽名驗證的大致流程以下圖所示:



三、jarsign和signapk工具

瞭解到完了簽名中的三個文件的知識點以後,下面繼續來看看Android中籤名的兩個工具:jarsign和signapk

關於這兩個工具開始的時候很容易混淆,感受他們兩到底有什麼區別嗎?

其實這兩個工具很好理解,jarsign是Java本生自帶的一個工具,他能夠對jar進行簽名的。而signapk是後面專門爲了Android應用程序apk進行簽名的工具,他們兩的簽名算法沒什麼區別,主要是簽名時使用的文件不同,這個就要引出第三個問題了。


四、keystore文件和pk8,x509.pem文件的區別

咱們上面瞭解到了jarsign和signapk兩個工具均可以進行Android中的簽名,那麼他們的區別在於簽名時使用的文件不同

jarsign工具簽名時使用的是keystore文件

signapk工具簽名時使用的是pk8,x509.pem文件

其中咱們在使用Eclipse工具寫程序的時候,出Debug包的時候,默認用的是jarsign工具進行簽名的,並且Eclipse中有一個默認簽名文件:


咱們能夠看到這個默認簽名的keystore文件,固然咱們能夠選擇咱們本身指定的keystore文件。

這裏還有一個知識點:

咱們看到上面有MD5和SHA1的摘要,這個就是keystore文件中私鑰的數據摘要,這個信息也是咱們在申請不少開發平臺帳號的時候須要填入的信息,好比申請百度地圖,微信SDK等,會須要填寫應用的MD5或者是SHA1信息


五、手動的簽名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他們之間是否是有什麼聯繫呢?答案是確定的,網上搜了一下,果真他們之間是能夠轉化的,這裏就不在分析如何進行轉化的,網上的例子貌似不少,有專門的的工具能夠進行轉化:


那麼到這裏咱們就弄清楚了這兩個簽名工具的區別和聯繫。


3、分析Android中籤名流程機制

下面咱們開始從源碼的角度去看看Android中的簽名機制和原理流程

由於網上沒有找到jarsigner的源碼,可是找到了signapk的源碼,那麼下面咱們就來看看signapk的源碼吧:

源碼位置:com/android/signapk/sign.java

經過上面的簽名時咱們能夠看到,Android簽名apk以後,會有一個META-INF文件夾,這裏有三個文件:

MANIFEST.MF

CERT.RSA

CERT.SF

下面來看看這三個文件究竟是幹啥的?

一、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<String, JarEntry> byName = new TreeMap<String, JarEntry>();

    for (Enumeration<JarEntry> 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包中的路徑。


二、下面再來看一下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<String, Attributes> entries = manifest.getEntries();
    for (Map.Entry<String, Attributes> entry : entries.entrySet()) {
        // Digest of the manifest stanza for this entry.
        print.print("Name: " + entry.getKey() + "\r\n");
        for (Map.Entry<Object, Object> 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<String, Attributes> entries = manifest.getEntries();
for (Map.Entry<String, Attributes> entry : entries.entrySet()) {
    // Digest of the manifest stanza for this entry.
    print.print("Name: " + entry.getKey() + "\r\n");
    for (Map.Entry<Object, Object> 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


三、最後咱們在來看一下CERT.RSA文件


這裏咱們看到的都是二進制文件,由於RSA文件加密了,因此咱們須要用openssl命令才能查看其內容

openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs –text


關於這些信息,能夠看下面這張圖:


咱們來看一下代碼:

/** 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格式的文件。


4、爲什麼要這麼來簽名

上面咱們就介紹了簽名apk以後的三個文件的詳細內容,那麼下面來總結一下,Android中爲什麼要用這種方式進行加密簽名,這種方加密是否是最安全的呢?下面咱們來分析一下,若是apk文件被篡改後會發生什麼。

首先,若是你改變了apk包中的任何文件,那麼在apk安裝校驗時,改變後的文件摘要信息與MANIFEST.MF的檢驗信息不一樣,因而驗證失敗,程序就不能成功安裝。
其次,若是你對更改的過的文件相應的算出新的摘要值,而後更改MANIFEST.MF文件裏面對應的屬性值,那麼一定與CERT.SF文件中算出的摘要值不同,照樣驗證失敗。
最後,若是你還不死心,繼續計算MANIFEST.MF的摘要值,相應的更改CERT.SF裏面的值,那麼數字簽名值一定與CERT.RSA文件中記錄的不同,仍是失敗。
那麼能不能繼續僞造數字簽名呢?不可能,由於沒有數字證書對應的私鑰。
因此,若是要從新打包後的應用程序能再Android設備上安裝,必須對其進行重簽名。

從上面的分析能夠得出,只要修改了Apk中的任何內容,就必須從新簽名,否則會提示安裝失敗,固然這裏不會分析,後面一篇文章會注重分析爲什麼會提示安裝失敗。


5、知識點梳理

一、數據指紋,簽名文件,證書文件的含義

1》數據指紋就是對一個數據源作SHA/MD5算法,這個值是惟一的

2》簽名文件技術就是:數據指紋+RSA算法

3》證書文件中包含了公鑰信息和其餘信息

4》在Android簽名以後,其中SF就是簽名文件,RSA就是證書文件咱們可使用openssl來查看RSA文件中的證書信息和公鑰信息

二、咱們瞭解了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文件之間能夠互相轉化


6、思考

咱們在分析了簽名技術以後,無心中發現一個問題,就是CERT.SF,MANIFEST.MF,這兩個文件中的內容的name字段都是apk中的資源名,那麼就有一個問題了,若是資源名很長,並且apk中的資源不少,那麼這兩個文件就會很大,那麼這裏咱們是否是能夠優化呢?後面在分析如何減少apk大小的文章中會繼續講解,這裏先提出這個問題。


資源下載:http://download.csdn.net/detail/jiangwei0910410003/9377046


總結

上面咱們就經過源碼來介紹了Android中的簽名過程,整個過程仍是很清楚的,文章寫得有點長,若是你們看的有問題的話,記得給我留言,後面我還會再寫一篇姊妹篇文章:Android中的簽名校驗過程詳解,期待中~~


PS: 關注微信,最新Android技術實時推送

相關文章
相關標籤/搜索