文章出處:http://www.limodev.cn/blog
昨天看了一下Android中的簽名機制,這里介紹一下Android中簽名用的Key的產(chǎn)生方法和簽名的原理。
產(chǎn)生Key
o 產(chǎn)生RSA私鑰(private key)
openssl genrsa -3 -out testkey.pem 2048
-3 是算法的參數(shù)(public exponent)。
2048 是私鑰長度。
testkey.pem 是輸出的文件。
o 產(chǎn)生PKCS#10格式的認(rèn)證請求。所謂認(rèn)證請求就是發(fā)給認(rèn)證機構(gòu)認(rèn)證的一個請求,它主要包括一個公鑰和一些相關(guān)信息(如組織名稱和聯(lián)系人郵件地址)。
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 \
-subj ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’
如果不提供最后兩個參數(shù),openssl會提示你輸入相關(guān)信息,這里的信息可以根據(jù)你自己的實際情況填寫。如:
openssl req -new -x509 -key testkey.pem -out testkey.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) [GB]:CN
State or Province Name (full name) [Berkshire]:GuangDong
Locality Name (eg, city) [Newbury]:ShenZhen
Organization Name (eg, company) [My Company Ltd]:Topwise
Organizational Unit Name (eg, section) []:Broncho
Common Name (eg, your name or your server’s hostname) []:broncho.cn
Email Address []:bronchosales@gmail.com
o 把私鑰的格式轉(zhuǎn)換成PKCS #8(Private-Key Information Syntax Standard.)
openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt
私鑰是不能讓別人知道的,否則就起不到保密的作用了。私鑰通常是要加密保存的,但這里指定了-nocryp,表示不加密。
Android提供了一個腳本mkkey.sh用來簡化上面的步驟:
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/emailAddress=android@android.com"
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/emailAddress=android@android.com'
openssl pkcs8 -in $1.pem -topk8 -outform DER -out $1.pk8 -nocrypt
簽名
Android提供了為jar/zip文件簽名的程序signapk.jar 。
它的用法如下:
Usage: signapk publickey.x509[.pem] privatekey.pk8 input.jar output.jar
第一個參數(shù)是公鑰,即前面第二步產(chǎn)生的testkey.x509.pem。
第二個參數(shù)是私鑰,即前面第三步產(chǎn)生的testkey.pk8。
第三個參數(shù)是要簽名的文件。
第四個參數(shù)是輸出的文件(即簽名后的文件)。
如:java -jar signapk.jar testkey.x509.pem testkey.pk8 update.zip update-signed.zip
現(xiàn)在我們來看看簽名到底做了些什么:
o 先為輸入的jar/zip文件中的所有文件生成SHA1數(shù)字簽名(除了CERT.RSA,CERT.SF和MANIFEST.MF)
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);
}
}
并把數(shù)字簽名信息寫入MANIFEST.MF
je = new JarEntry(JarFile.MANIFEST_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
manifest.write(outputJar);
o 對manifest簽名并寫入CERT.SF
// 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));
o 把對輸出文件的簽名和公鑰寫入CERT.RSA。
// CERT.RSA
je = new JarEntry(CERT_RSA_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureBlock(signature, publicKey, outputJar);
簽名的作用
簽名的主要目的為了檢測文件是否被別人修改了。但它并不能禁止別人修改,因為你完全重新生成簽名,但是你生成的簽名和原來是不一樣的。
用signapk.jar簽名android的update.zip文件【原創(chuàng)】
用signapk.jar簽名android的update.zip文件
linux系統(tǒng)下執(zhí)行:
java -jar out/host/linux-x86/framework/signapk.jar -w build/target/product/security/JBS.x509.pem build/target/product/security/JBS.pk8 out/target/product/JBS/update-not-signed.zip out/target/product/JBS/update.zip
用Android自帶的signapk.jar + .x509.pem + .pk8簽名應(yīng)用程序
http://lmdy2001.blog.163.com/blog/static/8423891020114262323816/
文件位置:可以在platform/build/target/product/security/中找到platform.pk8 platform.x509.pem等簽名文件,對應(yīng)不同的權(quán)限。
signapk.jar:由/platform/build/tools/signapk/編譯產(chǎn)出,可以在/out/host/linux-x86/framework/中找到。
簽名:
java -jar signapk.jar platform.x509.pem platform.pk8 MyDemo.apk MyDemo_signed.apk 得到具有對應(yīng)權(quán)限的APK
優(yōu)化APK:
zipalign -v 4 MyDemo_signed.apk MyDemo_new.apk
查循APK是否優(yōu)化過:
zipalign -c -v 4 MyDemo.apk