Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 簽名相關

android 簽名相關

編輯:關於Android編程

加密技術是最常用的安全保密手段,利用技術手段把明文變為密文(加密)傳送,到達目的地後再用相同或不同的手段還原(解密)。常見的加密算法可以分成三類,對稱加密算法,非對稱加密算法和HASH算法。前兩類是可逆的,即加密後的密文仍然可以轉換成明文,但Hash算法是不可逆的,即使在有源碼及密文的情況下也無法將明文還原出來,如MD5算法。

由於Java的語言特點及Android的開放性質,出現了越來越多的惡意程序。谷歌Android市場在也曾多次遭惡意開發者上傳基於正常應用篡改後的惡意軟件,雖然這些軟件已經被查出,但在將其下架前已經造成了幾十萬用戶被感染。這些惡意程序都是以已存在的成名的應用為載體,經過二次處理後植入惡意代碼,重新簽證後再次向市場發布,誘導用戶下載使用。為了避免這種情況的發生,保護自己的應用在未經自己允許的情況下慘遭篡改,保護自己的應用不會被人利用做一些傷害用戶的行為,本章節中將介紹這樣一種保護機制。

Android系統要求每一個安裝進系統的應用程序都是經過數字證書簽名的,數字證書的私鑰(即.keystore簽證文件)則保存在程序開發者的手中,簽證後的信息摘要保存在APK包中的.RSA文件中。數字證書用來標識應用程序的作者與應用程序之間建立信任關系。一旦證書被篡改,則.RSA文件被替換了,即表明應用程序的原作者不再為該應用負責。依照這個原理,可以在第一次運行程序時讀取APK中的.RSA摘要信息對其進行判斷是否是與經應用原作者簽名後產生的信息一致。如果一致則讓程序正常運行;如果不一致則表明應用被篡改過,提示用戶並終止運行。

可以通過以下方法獲取APK包中的.RSA信息:

Signature[] sigs = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures;

byte[] data = sigs[0].toByteArray();


在Android官方文檔中,對Signature類的定義是:在應用程序包及對該包進行簽名的證書間建立起不透明的、不可改變的代表關系。執行Signature.toByteArray()將返回.RSA的字節信息。

下面將把這些字節轉換成可閱讀的數字指紋信息:

// alg參數指定算法

MessageDigest algorithm = MessageDigest.getInstance(alg);

// 將狀態重圍到初始化,准備好進行計算Hash值。

algorithm.reset();

// 返回計算後的Hash值

algorithm.update(data);

// 將Hash值轉為可讀的16進制文本

byte[] dataHash = algorithm.digest();


通過MessageDigest來計算數字指紋信息,其算法核心是HASH函數。哈希函數提供了這樣一種計算過程:輸入一個長度不固定的字符串,返回一串定長度的字符串,即HASH值。

HASH函數主要可以解決以下兩個問題:一是無法通過HASH值得到原報文;二是不存在不同報文經HASH操作後生成相同HASH值。

這樣在數字簽名中就可以解決驗證簽名和用戶身份驗證、不可抵賴性的問題。在獲取MessageDigest時要指定所使用的算法名稱,常見的算法是專門用於加密處理的MD5和SHA1。這兩種算法產生一種128位信息摘要,除徹底地搜尋外,沒有更快的方法對其加以攻擊,而其搜索時間一般需要1025年之久,這樣即可保證信息在一段時間內的有效性與安全性。

使用MessageDigest時,養成一個良好的習慣是在讀取數據前將其reset()置初始化狀態,即使這個實例是剛實例化的,這樣盡量可以避免之前已讀的冗余數據對最後的結果產生負作用。接下來就是使用update()方法讀取待計算的數據,完成後調用digest()將返回計算後的HASH值dataHash數組。最後為了可讀性,通過自己實現的toHexString()把HASH值由byte轉為16進制文本。

在得到dataHash時,即可對應用程序是否正版進行判斷了,但一般為了簡便,把提前寫入的正版的指紋信息與最後HexString值進行比較,從而得出應用程序是否被篡改的結果。比較代碼如下:

txtVerify.setText(alg + "\n");



String result = "This soft is a pirated software.";



if (alg.equals(MD5)) {

        txtVerify.append("Original:" + "\n" + HASH_VALUE_MD5 + "\n");

        if (HASH_VALUE_MD5.equals(hexInfo)) {

                result = "This soft is a genuine software";

        }

} else if (alg.equals(SHA1)) {

        txtVerify.append("Original:" + "\n" + HASH_VALUE_SHA1 + "\n");

        if (HASH_VALUE_SHA1.equals(hexInfo)) {

                result = "This soft is a genuine software";

        }

}



txtVerify.append("Current:" + ":\n" + hexInfo + "\n");

txtVerify.append(result);

以上代碼中的HASH_VALUE_MD5和HASH_VALUE_SHA1分別是使用Code_Test_Key.keystore簽名後的APK實際計算出的HASH值。






以下信息來自網易:

一、簽名方法
方法一.源碼簽名(android簽名方法) 備注:幾乎所有的自動化簽名工具都是采用的這種方法 (1)生成簽名所需要的keypair:公鑰與私鑰 andoid源碼中提供了腳本build/target/product/security/mkkey.sh 來生成簽名所需要的key
if ["$1" == ""]; then
echo "Create a test certificate key."
echo "Usage: $0 NAME"
echo "Will generate NAME.pk8 and NAME.x509.pem"
echo " /C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]"
return
fi

openssl genrsa -3 -out $1.pem 2048

openssl req -new -x509 -key $1.pem -out $1.x509.pem -days 10000 \
-subj '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]'

openssl pkcs8 -in $1.pem -topk8 -outform DER -out $1.pk8 -nocrypt
從腳本中,我們可以得知,是采用以下步驟生成keypair的。
第一步:生成長度為2048位的RSA私鑰

root@bt:~/bubble example# openssl genrsa -3 -out test.pem 2048
Generating RSA private key, 2048 bit long modulus
...+++
...................................................................................+++
e is 3 (0x3)


root@bt:~/bubble example# cat test.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxJGCXH8i3XgogreH9oMoTaqUR6zTmblWUH3dOg7lV7F+cDDC
P4hPBItEumMGkwhHqdqXMrvAj3RlYVGq6iozWJDluUDzY095G7UuuiPRXr5q0vl4
t0kzPJIAon6kdbAl/0JFJqKLCeyk4aWsa4yRFBi0BWC7qg4ilLdHIZL0CFnRHK6F
9haXVxBBvDPdA06YT5MDqvThs/ZCY1BnGmBb+Srj8YJJ9Nvdxix5Dmqs5JDsn+L0
5OweZqwMcyKVMTrvjj921kJvReuHRRtVwE/xrSkusZITLZ45zySiRAi+NRR9hFlS
efla/8gyCXmCYcvMDOFu827QJpbzWhKgFUWRawIBAwKCAQEAgwusPaoXPlAbAc+v
+azFiRxi2nM3u9DkNak+JrSY5SD+9XXW1QWKAweDJuyvDLAvxpG6IdKAX6LuQOEc
nBwiOwtD0NX3l4pQvSN0fBfg6dRHN1D7JNt3fbarFv8YTnVuqiwuGcGyBp3DQRkd
nQhguBB4A5XScV7BuHova7dNWuVfLWJAgeSUckHZBUHKWkq6ETo63QBW9yqjwUKh
aLAZFbyBMvmhX+9oWgKBTmmr91TIA4z0JbkpPWD8LBuTKKld6FSrOEA432+SNZvW
WMjr2GxyPoE4+6kiB4EhnhQI7hOzSFHW7vD1dlxkDi+B7MvN+cgPqlZ0kvRO2v5V
5uz2GwKBgQD0s9PCzQnsdpOhUHUPAe6ztLk4Uy0y7NoWl7M/P7jEqTC73OP05oGx
FVGLri3l2X7g/NVUtgSEzTUBJH/rEnBJKaCjVgtW0eaIM5Hu3x/evDdUIDeIpe6V
4D4ko6z5XuHddsURO7VOOTQXA8B2xG3bb1y8dCZ3SDN3VMX9TkQbpwKBgQDNpMdi
ZjXMNRna49weee/NgQJzDEcsVFw2Kbk1vZ9xr19mSCfi/nMQKdcrap5FGBLfnbox
9lHbvWWRDHlNYcyZiB/Sq9bDJN2jwR+lXAKxLE8vM5i1DjHw46TLMz23cRUTIRl+
19qclQmE8HHIuiw7ptia/8aqAfUFvM8h7J4EnQKBgQCjIo0siLFITw0WNaNfVp8i
eHt64h4h8zwPD8zU1SXYcMsn6Jf4mavLY4uydB6ZO6nrUzjjJAMDM3irbaqctvWG
G8Bs5AePNpmwImFJ6hU/KCTiwCUFw/Rj6tQYbR37lJaTpINg0nje0M1krSr52Ek8
9Oh9osRPhXek4y6o3tgSbwKBgQCJGITsRCPdeLvnQpK++/Uzq1b3XYTIOD15cSYj
07+hH5Tu2sVB/vdgG+THnGmDZWHqaSbL+Yvn05kLXaYzlohmWr/hx+SCGJPCgL/D
kqx2HYofd7sjXsv17RiHd356S2NiFhD/OpG9uLEDSvaF0XLSbzsR/9nGq/iufd9r
8xQDEwKBgHVOxkAoYn4Q3DXhfeTrxpZEmg7lBTuZAg8A52xH/eVMVTSKwqw+NxfZ
wrU+fGQeruGm5mmOzwOuTDwywcM8qs0/gQVsUVliCMd6IbwDnN4dsNLsZdZp1nV7
rbi0sCmk218gLOQ9p2jv9i0BS8etSEkBwRzF99KgruMGtyd4R39b
-----END RSA PRIVATE KEY-----


第二步:生成x509格式的公鑰證書

root@bt:~/bubble example# openssl req -new -x509 -key test.pem -out test.x509.pem -days 10000
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:Mountain View
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Android
Organizational Unit Name (eg, section) []:Android
Common Name (eg, YOUR name) []:Android
Email Address []:[email protected]


root@bt:~/bubble example# cat test.x509.pem
-----BEGIN CERTIFICATE-----
MIIEqjCCA5KgAwIBAgIJALNXgLhW3YPbMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAg
Fw0xMjEyMTMwNzQ1MDZaGA8xOTA0MDMyNTAxMTY1MFowgZQxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAw
DgYDVQQKEwdBbmRyb2lkMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQDEwdBbmRy
b2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIIBIDANBgkq
hkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAxJGCXH8i3XgogreH9oMoTaqUR6zTmblW
UH3dOg7lV7F+cDDCP4hPBItEumMGkwhHqdqXMrvAj3RlYVGq6iozWJDluUDzY095
G7UuuiPRXr5q0vl4t0kzPJIAon6kdbAl/0JFJqKLCeyk4aWsa4yRFBi0BWC7qg4i
lLdHIZL0CFnRHK6F9haXVxBBvDPdA06YT5MDqvThs/ZCY1BnGmBb+Srj8YJJ9Nvd
xix5Dmqs5JDsn+L05OweZqwMcyKVMTrvjj921kJvReuHRRtVwE/xrSkusZITLZ45
zySiRAi+NRR9hFlSefla/8gyCXmCYcvMDOFu827QJpbzWhKgFUWRawIBA6OB/DCB
+TAdBgNVHQ4EFgQU1aCdtEBdGQLhO7nqnaR4pCJW0q0wgckGA1UdIwSBwTCBvoAU
1aCdtEBdGQLhO7nqnaR4pCJW0q2hgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK
EwdBbmRyb2lkMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQDEwdBbmRyb2lkMSIw
IAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tggkAs1eAuFbdg9swDAYD
VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAq/BUGCGWpF1E7WQ/vmoDrZ4r
2XTmyHycQSFpvozeKjvlBD1ESNchEWvxOSFiFrCX/OqFwEn8sQRMClpR4fdXmKrv
5GxrXN3M6ZNOmr7cNGINNeJkKhQfepaUE9bdcdSyzQsgajF0rhYosyW48k7DW5J8
zXoBIrUgGV1KhnIPci+Jg7+QBhXGZxIOyVqDg8q8h8CJgMldyyPNdmhHDAH497Sp
EgIioD/95Gk5DnrHDwlTo54vh5hT2KEjcfkMNEhXpQFgYJog+HYcJwjdFoH0ZA+P
2lZ9o6hT3Dkc1PzdgzehVVa+ys0SZ4pHMPpx2z5T9cR25wO15mC8inkcA5onqQ==
-----END CERTIFICATE-----


第三步:生成符合PKCS8標注的私鑰文件

root@bt:~/bubble example# openssl pkcs8 -in test.pem -topk8 -outform DER -out test.pk8 -nocrypt


可以在http://blog.csdn.net/anxuegang/article/details/6157927看到不同證書的格式的介紹
(2)用keypair簽名 android源碼中提供了簽名生成工具,和簽名所需要的公鑰,私鑰文件。其中sigapk.jar為簽名工具,platform.x509.pem為公鑰文件,platform.pk8為私鑰文件。 網上較流行的AutoSign工具就是采用的這種方法。
#!/bin/sh
MY_SDK_HOME=~/platform/android/main/mydroid/
PEM=${MY_SDK_HOME}/build/target/product/security/platform.x509.pem
PK8=${MY_SDK_HOME}/build/target/product/security/platform.pk8

if [ $# -ne 2 ]
then
echo Usage $0 in.apk out.apk
exit 1
fi
java -jar ${MY_SDK_HOME}/out/host/linux-x86/framework/signapk.jar \
${PEM} ${PK8} $1 $2


第四步:簽名

root@bt:~/bubble example/dis# java -jar signapk.jar test.x509.pem test.pk8 unsig.apk signapk.apk



第五步:優化,主要是為了數據邊界與文件的開始是內存對齊的

root@bt:~/bubble example# zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk



方法二、命令行簽名(Sun 簽名方法) 工具:keytool,jarsigner 第一步:生成keystore

root@bt:~# keytool -genkey -alias dani.keystore -keyalg RSA -validity 4000 -keystore dani.keystore

第二步:簽名

oot@bt:~/bubble example/dis/FrozenBubbleSignapk/META-INF# jarsigner -keystore dani.keystore -digestalg SHA1 -sigalg MD5withRSA -signedjar signed.apk unsigend.apk dani.keystore


第三步:優化

root@bt:~/bubble example# zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk


二、簽名過程分析 無論采取哪種簽名方法,都會APK中生成META-INF文件夾,該文件夾包含三個文件 1. MANIFEST.MF 2.CERT.SF 3.CERT.RSA
生成過程如下: 第一步:.首先對文件夾中的文件采用sha1-base64生成摘要,將這些摘要信息保存在MANIFEST.MF中 我使用以下腳本對比了MANIFEST.MF中對應的值,符合

#!/usr/bin/perl
use Digest::SHA1 qw(sha1 sha1_hex sha1_base64);

die "$0 requires one arguments (file pathname) . \n" if $#ARGV !=0;

$filename=shift;

open FH,$filename or die "cannot open $filename";


$sha1 = Digest::SHA1->new;

$sha1->addfile(*FH);

$digest= $sha1->b64digest;

print $digest,"\n";

close FH;


第二步:.對包括MANIFEST.MF文件在內的所有文件采用sha1-base64生成摘要,方法如下。



SHA1("Name:
filename"+CR+LF+"SHA1-Digest: "+SHA1(file_content)+CR+LF+CR+LF)



然後將這些摘要信息保存在CERT.MF中。 備注:采用android(Android signapk.jar與Sun jarsigner兩種簽名方法生成的CERT.MF文件弱有不同。

3. 對第二步中的摘要信息,采用選取的簽名算法(SHA1-RSA或者MD5-RSA),用私鑰進行簽名,同時把公鑰證書與簽名信息存放在CERT.RSA中
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));

je = new JarEntry(CERT_RSA_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureBlock(signature, publicKey, outputJar);


三、簽名校驗 由簽名生成過程,我們可以知道簽名做了兩件事情: 1. 完整性校驗,可以發現APK包中的文件是否存在變動。 如果對文件進行修改,對應的SHA1值會發生變動。
2.APK發布作者身份唯一性校驗 當在android設備上安裝apk包時,會從存放在CERT.RSA中的公鑰證書中提取公鑰,進行RSA解密來校驗安裝包的身份。
使用以下命令,可以校驗APk包的簽名狀況

root@bt:~/bubble example/dis# jarsigner -verify -certs -verbose FrozenBubble-modify-sig.apk

4689 Wed Dec 12 15:56:44 CST 2012 META-INF/MANIFEST.MF
4810 Wed Dec 12 15:56:44 CST 2012 META-INF/DANI_KEY.SF
913 Wed Dec 12 15:56:44 CST 2012 META-INF/DANI_KEY.RSA
sm 29099 Wed Dec 12 15:10:22 CST 2012 assets/levels.txt

X.509, CN=dani lee, OU=taomee, O=taomee, L=shanghai, ST=CA, C=CA
[certificate is valid from 12/12/12 3:43 PM to 11/25/23 3:43 PM]

sm 25213 Wed Dec 12 15:20:14 CST 2012 res/drawable/app_frozen_bubble.png


使用不同的key生成的簽名信息會不同,不同的私鑰對應不同的公鑰,因此最大的區別是簽名證書中存放的公鑰會不同,所以我們可以通過提取CERT.RSA中的公鑰來檢查安裝包是否被重新簽名了。
具體的APk簽名對比實現方法ttp://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html 可以在這裡查看到,非常佩服這位博主,是個java高手,幾乎每天都在更新博客。
參考: http://www.blogjava.net/MEYE/articles/357174.html http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved