獲取APK簽名證書的SHA1和MD5

代碼說明一切,請直接閱讀代碼。 java

package com.mycompany.myapp5;

import android.app.*;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.*;
import android.widget.*;
import java.io.*;
import java.security.cert.CertificateFactory;
import java.util.*;
import java.security.cert.X509Certificate;
import android.content.pm.*;
import java.security.MessageDigest;
import java.security.cert.*;

public class MainActivity extends Activity 
{
	ByteArrayOutputStream bos=new ByteArrayOutputStream();
	OutputStreamWriter osw=new OutputStreamWriter(bos);
	PrintWriter pw=new PrintWriter(osw, true);

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
		ScrollView sv=new ScrollView(this);
		TextView tv=new TextView(this);

		sv.addView(tv);
		setContentView(sv);
		getCertMsg(this.getPackageName());
		pw.flush();
        tv.setText(bos.toString());
    }
	private void getCertMsg(String packageName)
	{
		PackageInfo pis;
		try
		{
			pis = this.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
			Signature[] sigs = pis.signatures; //簽名
			pw.println("sigs.len:" + sigs.length);

			pw.println("sigs[0] data:");
			pw.println(toHex(sigs[0].toByteArray()));
			pw.println();

			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
//獲取證書
			X509Certificate cert = (X509Certificate) certFactory.generateCertificate(
				new ByteArrayInputStream(sigs[0].toByteArray()));
//獲取證書發行者 可根據證書發行者來判斷該應用是否被二次打包(被破解的應用從新打包後,簽名與原包必定不一樣,據此能夠判斷出該應用是否被人作過改動)

			pw.println("cert data:");
			pw.println(toHex(cert.getEncoded()));
			pw.println();

			MessageDigest sha1=MessageDigest.getInstance("SHA1");
			byte[] bs=sha1.digest(cert.getEncoded());
			String certSha1=toHex(bs);

			MessageDigest md5=MessageDigest.getInstance("md5");
			byte[] bs2=md5.digest(cert.getEncoded());
			String certMd5=toHex(bs2);
			pw.println("sha1:");
			pw.println(certSha1);
			pw.println();
			pw.println("md5");
			pw.println(certMd5);
			pw.println();
			pw.println(cert.getIssuerDN().toString());
			pw.println(cert.getSubjectDN().toString());
		}
		catch (CertificateException e)
		{

			e.printStackTrace(pw);
		}
		catch (Exception e)
		{
			e.printStackTrace(pw);
		}

	}
	char[] cs=new char[16];
	{
		for (int i=0;i < 10;i++)
		{
			cs[i] = (char) ('0' + i);
		}
		for (int i=10;i < 16;i++)
		{
			cs[i] = (char) ('A' + i - 10);
		}
	}
	String toHex(byte[] bs)
	{
		char[] cs=new char[bs.length * 2];
		int x;
		for (int i=0;i < bs.length;i++)
		{
			x = bs[i] & 0xff;
			cs[2 * i] = this.cs[x / 16];
			cs[2 * i + 1] = this.cs[x % 16];
		}
		return new String(cs);
	}
}

上面的cert data=cert.getEncoded()); android

cert data就是pem文件的實際數據,也就是說,pem文件用的Base64編碼,再轉回byte[] 就是certdata了。 app

在上面的例子中,sigs[0].toByteArray()獲得的數據和cert data是同樣的, ide

再說說什麼是pem文件,用過signApk工具的會在該工具的目錄發現有兩個文件,分別是.pem文件和.pk8文件 工具

cert data等於.pem文件的內容的主體部分,也便是-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----
之間的部分,不包括這兩個標記.BEGIN CERTIFICATE這個標記多是其餘類似的標記,openssl生產的就出現這種狀況。 this

對cert data SHA1摘要就和.pem公鑰證書的SHA1指紋同樣了,同理md5也同樣。 編碼

看到這裏,有人會問,我要的是 keystore證書的指紋,你怎麼跟我討論這個? .net

先別急,keystore證書的指紋和pem公鑰證書的指紋是同樣的,能夠使用openssl將keystore的證書轉成.pem公鑰證書和.pk8私鑰。轉化後證書的指紋信息是同樣的。提供個如何轉化證書的連接 http://blog.csdn.net/ilittleone/article/details/17914995 code

說到這裏,你應該明白了吧。 blog

相關文章
相關標籤/搜索