zoukankan      html  css  js  c++  java
  • Android App安装启动时签名校验

    Android发布时签名

    • 分发:即部署,需要签名。若要发布 .APK,必须首先使用签名密钥(也称为证书)对它进行签名。创建新证书(里面包含一对公私钥,个人/公司的信息)

      秘钥的位置默认【加固需要用到】:C:UsersUSERNAMEAppDataLocalXamarinMono for AndroidKeystore

             参考:对 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:UsershuyAppDataLocalXamarinMono for AndroidKeystorehuyNewhuyNew.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运行时签名校验

  • 相关阅读:
    记录「十一月做题记录」
    题解「GMOJ6898 【2020.11.27提高组模拟】第二题」
    题解「CFGYM102331B Bitwise Xor」
    题解「Japan Alumni Group Summer Camp 2018 Day 2J AB Sort」
    题解「AGC048B Bracket Score」
    题解「中位数之中位数 median」
    记录「十月做题记录」
    测试「2020牛客NOIP赛前集训营-提高组(第五场)」
    测试「20201028测试总结」
    定时提醒助手
  • 原文地址:https://www.cnblogs.com/peterYong/p/12660488.html
Copyright © 2011-2022 走看看