標籤:
本文轉載自: http://www.wjdiankong.cn/android%E7%AD%BE%E5%90%8D%E6%9C%BA%E5%88%B6%E4%B9%8B-%E7%AD%BE%E5%90%8D%E8%BF%87%E7%A8%8B%E8%AF%A6%E8%A7%A3/
一、前言
又是過了好長時間,沒寫文章的雙手都有點難受了。今天是聖誕節,還是得上班。因為前幾天有一個之前的同事,在申請SDK的時候,遇到簽名的問題,問了我一下,結果把我難倒了。。我說Android中的簽名大家都會熟悉的,就是為了安全,不讓別人修改你的apk,但是我們真正的有瞭解多少呢?所以準備兩篇文章好好介紹一下Android中籤名機制。
在說道Android簽名之前,我們需要瞭解的幾個知識點
1、資料摘要(資料指紋)、簽名檔案,認證檔案
2、jarsign工具簽名和signapk工具簽名
3、keystore檔案和pk8檔案,x509.pem檔案的關係
4、如何手動的簽名apk
上面介紹的四個知識點,就是今天介紹的核心,我們來一一看這些問題。
二、準備知識
首先來看一下資料摘要,簽名檔案,認證檔案的知識點
1、資料摘要
這個知識點很好理解,百度百科即可,其實他也是一種演算法,就是對一個資料來源進行一個演算法之後得到一個摘要,也叫作資料指紋,不同的資料來源,資料指紋肯定不一樣,就和人一樣。
訊息摘要演算法(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檔案中私密金鑰的資料摘要,這個資訊也是我們在申請很多開發平台帳號的時候需要填入的資訊,比如申請百度地圖,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.MFManifest 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包中的路徑。
2、下面再來看一下CERT.SF檔案內容
這裡的內容感覺和MANIFEST.MF的內容差不多,來看看代碼吧:
//CERT.SFSignature 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
3、最後我們在來看一下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格式的檔案。
四、為何要這麼來簽名
上面我們就介紹了簽名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大小的文章中會繼續講解,這裡先提出這個問題。
資源下載:http://download.csdn.net/detail/jiangwei0910410003/9377046
總結
上面我們就通過源碼來介紹了Android中的簽名過程,整個過程還是很清楚的,文章寫得有點長,如果大家看的有問題的話,記得給我留言,後面我還會再寫一篇姊妹篇文章:Android中的簽名校正過程詳解,期待中~~
[轉載] Android簽名機制之—簽名過程詳解