Android發布時簽名
- 分發:即部署,需要簽名。若要發布 .APK,必須首先使用簽名密鑰(也稱為證書)對它進行簽名。創建新證書(里面包含一對公私鑰,個人/公司的信息)
秘鑰的位置默認【加固需要用到】:C:\Users\USERNAME\AppData\Local\Xamarin\Mono for Android\Keystore\
Android KeyStore以及打包簽名
Android KeyStore + FingerprintManager 存儲密碼
安卓密鑰庫(允許你存儲加密密鑰),指紋識別中也有創建key
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; } } }
測試
//測試簽名 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構造函數中傳入的真實值是否相等即可