zoukankan      html  css  js  c++  java
  • Unity3d获取APK签名及公钥的方法

          在Unity3d项目中获取APK包签名公钥的方法,核心思想就是通过JNI调用Android提供的方法。不过Unity3d提供了比JNI更上一层的类AndroidJavaObject以及继承它的AndroidJavaClass,帮助开发者省去很多工作。这两种类型的函数及内部原理可以看Unity3d官网,也可以反编译看里面的代码,直接说用法。

          首先要获取到当前运行程序的Activity才好继续以后的操作。Unity3d在程序启动时记录下了这个值,可以通过UnityPlayer类的静态字段currentActivity来取得,UnityPlayer是由UnityPlayerActivity这个继承自Activity的类在onCreate时创建并传入当前Activity(详细流程可以通过jd-gui或反编译项目smali查看)。取到Activity以后就可以getPackageManager、getPackageInfo来获取到签名。得到的签名据说保存了公钥以及其他一些信息,这个没有具体深入了解,但是可以从签名获取到公钥是一定可以的,CertificateFactory的generateCertificate、getPublicKey方法取得最终值。下面是完整代码,注释对应java代码:

     private byte[] GetSignature()
        {
            //Player = new UnityPlayer();
            AndroidJavaClass Player = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            //Activity = Player.currentActivity;
            AndroidJavaObject Activity = Player.GetStatic<AndroidJavaObject>("currentActivity");
            //PackageManager = Activity.getPackageManager();
            AndroidJavaObject PackageManager = Activity.Call<AndroidJavaObject>("getPackageManager");
            //GET_SIGNATURES = PackageManager.GET_SIGNATURES;
            int GET_SIGNATURES = PackageManager.GetStatic<int>("GET_SIGNATURES");
            //PackageInfo = PackageManager.getPackageInfo("com.ztx.uni", PackageManager.GET_SIGNATURES);
            AndroidJavaObject PackageInfo = PackageManager.Call<AndroidJavaObject>("getPackageInfo", "com.ztx.uni", GET_SIGNATURES);
            //Signatures = PackageInfo.signatures;
            AndroidJavaObject[] Signatures = PackageInfo.Get<AndroidJavaObject[]>("signatures");
            //return Signatures[0].toByteArray();
            return (Signatures != null && Signatures.Length > 0) ? Signatures[0].Call<byte[]>("toByteArray") : null;
        }
    
        private string GetPublicKey()
        {
            byte[] Signatures = GetSignature();
    
            if (Signatures != null)
            {
                //CCertificateFactory = new CertificateFactory();
                AndroidJavaClass CCertificateFactory = new AndroidJavaClass("java.security.cert.CertificateFactory");
                //OCertFactory = CCertificateFactory.getInstance();
                AndroidJavaObject OCertFactory = CCertificateFactory.CallStatic<AndroidJavaObject>("getInstance", "X.509");
                //OByteArrayInputStream = new ByteArrayInputStream(Signatures);
                AndroidJavaObject OByteArrayInputStream = new AndroidJavaObject("java.io.ByteArrayInputStream", Signatures);
                //OX509Certificate = OCertFactory.generateCertificate(OByteArrayInputStream);
                AndroidJavaObject OX509Certificate = OCertFactory.Call<AndroidJavaObject>("generateCertificate", OByteArrayInputStream);
                //OPublicKey = OX509Certificate.getPublicKey();
                AndroidJavaObject OPublicKey = OX509Certificate.Call<AndroidJavaObject>("getPublicKey");
    
                string publickey = OPublicKey.Call<string>("toString");
                AndroidJavaObject CString = new AndroidJavaObject("java/lang/String", publickey);
                int start = CString.Call<int>("indexOf", "modulus");
                int end = CString.Call<int>("indexOf", "public");
    
                if (start >= 0 && end >= 0)
                {
                    return CString.Call<string>("substring", start + 8, end - 1);
                }
            }
            
            return null;
        }




    在GetPublicKey()中取得的OPublicKey是如下的形式:
    OpenSSLRSAPublicKey
    {modulus=d6931904dec60b24b1edc762e0d9d8253e3ecd6ceb1de2ff068ca8e8bca8cd6bd3786ea70aa76ce
    60ebb0f993559ffd93e77a943e7e83d4b64b8e4fea2d3e656f1e267a81bbfb230b578c20443be4c7218b846f
    5211586f038a14e89c2be387f8ebecf8fcac3da1ee330c9ea93d0a7c3dc4af350220d50080732e0809717ee6
    a053359e6a694ec2cb3f284a0a466c87a94d83b31093a67372e2f6412c06e6d42f15818dffe0381cc0cd444d
    a6cddc3b82458194801b32564134fbfde98c9287748dbf5676a540d8154c8bbca07b9e247553311c46b9af76
    fdeeccc8e69e7c8a2d08e782620943f99727d3c04fe72991d99df9bae38a0b2177fa31d5b6afee91f,publicExponent=3}


    而我们要的只是其中的256位公钥,所以在函数后面取了modulus和publicExponent之间的值。至此全部工作结束,很简单吧,如果在ndk中做公钥提取也是这个道理,不过要写很多很多代码。


    转载地址:http://m.blog.csdn.net/blog/s10141303/38260469
  • 相关阅读:
    mysql数据恢复
    数据库备份脚本
    SHELL syntax error:unexpected end of file 提示错误
    shell script 的追踪与 debug
    mysql Host ‘XXXXXX’ is blocked because of many connection errors
    linux下MySQL 5.6源码安装
    C# 数据库并发的解决方案(通用版、EF版)
    Thread(线程)四
    C#线程系列讲座(1):BeginInvoke和EndInvoke方法
    在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
  • 原文地址:https://www.cnblogs.com/hacker13a/p/4960376.html
Copyright © 2011-2022 走看看