代码说明一切,请直接阅读代码。 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