Android App運(yùn)行時(shí)簽名校驗(yàn)

有時(shí)候我們?yōu)榱朔乐棺约旱膽?yīng)用被反編譯后重新打包,不得不采取運(yùn)行時(shí)進(jìn)行簽名校驗(yàn)的方式。
因?yàn)闀?huì)經(jīng)常用到,所以在這里整理了一下校驗(yàn)方式。

public class SignCheck {
    private Context context;
    private String cer = null;
    private String realCer = null;
    private static final String TAG = "SignCheck";
 
    public SignCheck(Context context) {
        this.context = context;
        this.cer = getCertificateSHA1Fingerprint();
    }
 
    public SignCheck(Context context, String realCer) {
        this.context = context;
        this.realCer = realCer;
        this.cer = getCertificateSHA1Fingerprint();
    }
 
    public String getRealCer() {
        return realCer;
    }
 
    /**
     * 設(shè)置正確的簽名
     *
     * @param realCer
     */
    public void setRealCer(String realCer) {
        this.realCer = realCer;
    }
 
    /**
     * 獲取應(yīng)用的簽名
     *
     * @return
     */
    public String getCertificateSHA1Fingerprint() {
        //獲取包管理器
        PackageManager pm = context.getPackageManager();
 
        //獲取當(dāng)前要獲取 SHA1 值的包名,也可以用其他的包名,但需要注意,
        //在用其他包名的前提是,此方法傳遞的參數(shù) Context 應(yīng)該是對(duì)應(yīng)包的上下文。
        String packageName = context.getPackageName();
 
        //返回包括在包中的簽名信息
        int flags = PackageManager.GET_SIGNATURES;
 
        PackageInfo packageInfo = null;
 
        try {
            //獲得包的所有內(nèi)容信息類
            packageInfo = pm.getPackageInfo(packageName, flags);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
 
        //簽名信息
        Signature[] signatures = packageInfo.signatures;
        byte[] cert = signatures[0].toByteArray();
 
        //將簽名轉(zhuǎn)換為字節(jié)數(shù)組流
        InputStream input = new ByteArrayInputStream(cert);
 
        //證書(shū)工廠類,這個(gè)類實(shí)現(xiàn)了出廠合格證算法的功能
        CertificateFactory cf = null;
 
        try {
            cf = CertificateFactory.getInstance("X509");
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        //X509 證書(shū),X.509 是一種非常通用的證書(shū)格式
        X509Certificate c = null;
 
        try {
            c = (X509Certificate) cf.generateCertificate(input);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        String hexString = null;
 
        try {
            //加密算法的類,這里的參數(shù)可以使 MD4,MD5 等加密算法
            MessageDigest md = MessageDigest.getInstance("SHA1");
 
            //獲得公鑰
            byte[] publicKey = md.digest(c.getEncoded());
 
            //字節(jié)到十六進(jìn)制的格式轉(zhuǎn)換
            hexString = byte2HexFormatted(publicKey);
 
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (CertificateEncodingException e) {
            e.printStackTrace();
        }
        return hexString;
    }
 
    //這里是將獲取到得編碼進(jìn)行16 進(jìn)制轉(zhuǎn)換
    private String byte2HexFormatted(byte[] arr) {
 
        StringBuilder str = new StringBuilder(arr.length * 2);
 
        for (int i = 0; i <arr.length; i++) {
            String h = Integer.toHexString(arr[i]);
            int l =h.length();
            if (l == 1)
                h = "0" + h;
            if (l > 2)
                h = h.substring(l - 2, l);
            str.append(h.toUpperCase());
            if (i < (arr.length - 1))
                str.append(':');
        }
        return str.toString();
    }
 
    /**
     * 檢測(cè)簽名是否正確
     * @return true 簽名正常 false 簽名不正常
     */
    public boolean check() {
 
        if (this.realCer != null) {
            cer = cer.trim();
            realCer = realCer.trim();
            if (this.cer.equals(this.realCer)) {
                return true;
            }
        }else {
            Log.e(TAG, "未給定真實(shí)的簽名 SHA-1 值");
        }
        return false;
    }
}

使用方法:
首先使用 keytool 獲取簽名的 sha-1 值,命令為 keytool -list -v -keystore xxx.jks (將 xx.jks 換成你的應(yīng)用簽名所用文件, 這里會(huì)提示輸入 keystore 的密碼 ps:簽名文件在eclipse 是 .keystore 文件, 在 Android Studio中就是 .jks 文件))

然后使用如下代碼校驗(yàn)簽名:


SignCheck signCheck = new SignCheck(this,"27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA");
  if(signCheck.check()) {
  //TODO 簽名正常
  }else                {
  //TODO 簽名不正確
  newAlertDialog.Builder(this).setMessage("請(qǐng)前往官方渠道下載正版 app, http://.....").setPositiveButton("確定",null).show();
  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容