Android App安裝啟動時簽名校驗


Android發布時簽名

  • 分發:即部署,需要簽名。若要發布 .APK,必須首先使用簽名密鑰(也稱為證書)對它進行簽名。創建新證書(里面包含一對公私鑰,個人/公司的信息)

    秘鑰的位置默認【加固需要用到】:C:\Users\USERNAME\AppData\Local\Xamarin\Mono for Android\Keystore\

         參考:對 Android 應用程序包進行簽名

Android KeyStore以及打包簽名

Android KeyStore + FingerprintManager 存儲密碼

安卓密鑰庫(允許你存儲加密密鑰),指紋識別中也有創建key

證書Certificate以及android打包簽名

Android上App升級更新

安卓系統本身在安裝app時會對app驗證簽名。

測試步驟: 在本機上有一個低版本的app,然后安裝一個高版本的app(分發時用不同的證書簽名),

安裝提示:安裝失敗“更新包與已安裝應用的簽名不一致”

建議卸載,卸載當前版本后,可以安裝成功!(這個沒法控制用戶,,所以可以考慮在app啟動時驗證簽名)

App啟動時檢測簽名是否正確

對比apk簽名證書的SHA1值是否自己用的簽名證書的值,而不是被別人篡改過的證書的值(防止自己的應用被反編譯后重新打包)

1、獲取自己對app分發時簽名證書的SHA1值

首先進入CMD,然后輸入:
keytool -exportcert -list -v -alias huyNew -keystore "C:\Users\huy\AppData\Local\Xamarin\Mono for Android\Keystore\huyNew\huyNew.keystore"
回車

在提示下輸入密鑰口令(是自己設置的密碼) (注:此時輸入字符cmd是不顯示的,請輸入完整后直接回車。如果失敗說明你輸錯了)

參考:

如何使用 keytool 獲取簽名證書的 SHA-1 哈希值

查找密鑰存儲的簽名

2、Xamarin.Android下獲取app證書SHA1值

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Java.IO;
using Java.Security;
using Java.Security.Cert;
using Signature = Android.Content.PM.Signature;

namespace AndroidDevice.Droid
{
    /// <summary>
    /// 驗證簽名
    /// </summary>
    public class SignCheck
    {
        private Context context;
        /// <summary>
        /// 應用的簽名
        /// </summary>
        public String cer = null;
        /// <summary>
        /// 真實的證書
        /// </summary>
        private String realCer = null;
        private static 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;
        }

        /// <summary>
        /// 獲取應用的簽名
        /// </summary>
        /// <returns></returns>
        public String GetCertificateSHA1Fingerprint()
        {
            //獲取包管理器
            PackageManager pm = context.PackageManager;

            //獲取當前要獲取 SHA1 值的包名,也可以用其他的包名,但需要注意,
            //在用其他包名的前提是,此方法傳遞的參數 Context 應該是對應包的上下文。
            String packageName = context.PackageName;

            //返回包括在包中的簽名信息。。還可以獲取簽名信息等 PackageInfoFlags.SigningCertificates
            var packageInfo = pm.GetPackageInfo(context.PackageName, PackageInfoFlags.Signatures);

            //簽名信息
            List<Signature> signatures = packageInfo.Signatures?.ToList();
            if (signatures == null || signatures.Count == 0)
            {
                return "";
            }
            byte[] cert = signatures[0].ToByteArray();

            //將簽名轉換為字節數組流
            //InputStream input = new ByteArrayInputStream(cert);
            System.IO.Stream input = new MemoryStream(cert);

            //證書工廠類,這個類實現了出廠合格證算法的功能
            CertificateFactory cf = null;

            try
            {
                cf = CertificateFactory.GetInstance("X509");
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(TAG + e.StackTrace);
            }

            //X509 證書,X.509 是一種非常通用的證書格式
            X509Certificate c = null;

            try
            {
                c = (X509Certificate)cf.GenerateCertificate(input);
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(TAG + e.StackTrace);
            }

            String hexString = null;

            try
            {
                //加密算法的類,這里的參數可以使 MD4,MD5 等加密算法
                MessageDigest md = MessageDigest.GetInstance("SHA1");

                //獲得公鑰
                byte[] publicKey = md.Digest(c.GetEncoded());

                //字節到十六進制的格式轉換
                hexString = byte2HexFormatted(publicKey);

            }
            catch (NoSuchAlgorithmException e)
            {
                System.Diagnostics.Debug.WriteLine(TAG + e.StackTrace);
            }
            catch (CertificateEncodingException e)
            {
                System.Diagnostics.Debug.WriteLine(TAG + e.StackTrace);
            }
            return hexString;
        }

        //這里是將獲取到得編碼進行16 進制轉換
        private String byte2HexFormatted(byte[] arr)
        {

            StringBuilder str = new StringBuilder(arr.Length * 2);

            for (int i = 0; i < arr.Length; i++)
            {
                String h = arr[i].ToString("X2");
                int l = h.Length;
                if (l == 1)
                    h = "0" + h;
                if (l > 2)
                    h = h.Substring(l - 2, l);
                str.Append(h.ToUpper());
                if (i < (arr.Length - 1))
                    str.Append(':');
            }
            return str.ToString();
        }


        /// <summary>
        /// 檢測簽名是否正確
        /// </summary>
        /// <returns></returns>
        public bool check()
        {
            if (this.realCer != null)
            {
                cer = cer.Trim();
                realCer = realCer.Trim();
                if (this.cer.Equals(this.realCer))
                {
                    return true;
                }
            }
            else
            {
                System.Diagnostics.Debug.WriteLine(TAG + "未給定真實的簽名 SHA-1 值");
            }
            return false;
        }
    }
}
View Code

測試

//測試簽名
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 簽名不正確
Toast.MakeText(this, "請前往官方渠道下載正版 app", ToastLength.Long);
}

LoadApplication(new App(signCheck.cer));
signCheck.cer 為當前app的簽名證書SHA1值。判斷它與SignCheck構造函數中傳入的真實值是否相等即可

參考:Android App運行時簽名校驗

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM