[unity]Unity3d获取APK签名及公钥的方法

简介: 在Unity3d项目中获取APK包签名公钥的方法,核心思想就是通过JNI调用Android提供的方法。不过Unity3d提供了比JNI更上一层的类AndroidJavaObject以及继承它的AndroidJavaClass,帮助开发者省去很多工作。

在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中做公钥提取也是这个道理,不过要写很多很多代码。。

相关文章
|
3月前
|
语音技术 开发工具 图形学
Unity与IOS⭐一、百度语音IOS版Demo调试方法
Unity与IOS⭐一、百度语音IOS版Demo调试方法
|
6月前
|
机器学习/深度学习 Java Shell
[RK3568][Android12.0]--- 系统自带预置第三方APK方法
[RK3568][Android12.0]--- 系统自带预置第三方APK方法
655 0
|
3月前
|
Java Android开发 Windows
使用keytool查看Android APK签名
本文介绍了如何使用Windows命令行工具和keytool查看APK的签名信息,并提供了使用AOSP环境中的signapk.jar工具对APK进行系统签名的方法。
387 0
使用keytool查看Android APK签名
|
3月前
|
前端开发 图形学
Unity精华☀️UI和物体可见性的判断方法
Unity精华☀️UI和物体可见性的判断方法
|
5月前
|
Ubuntu Android开发
蓝易云 - Ubuntu上导出APP的base.apk方法说明
注意:在实际的生产环境中,你应该使用 `assembleRelease`任务来构建一个用于发布的Release版本的APK,并且你需要提前配置好签名信息。
192 58
|
3月前
|
图形学 C# 开发者
全面掌握Unity游戏开发核心技术:C#脚本编程从入门到精通——详解生命周期方法、事件处理与面向对象设计,助你打造高效稳定的互动娱乐体验
【8月更文挑战第31天】Unity 是一款强大的游戏开发平台,支持多种编程语言,其中 C# 最为常用。本文介绍 C# 在 Unity 中的应用,涵盖脚本生命周期、常用函数、事件处理及面向对象编程等核心概念。通过具体示例,展示如何编写有效的 C# 脚本,包括 Start、Update 和 LateUpdate 等生命周期方法,以及碰撞检测和类继承等高级技巧,帮助开发者掌握 Unity 脚本编程基础,提升游戏开发效率。
84 0
|
3月前
|
C# 图形学 数据安全/隐私保护
Unity数据加密☀️反射的用法:变量、属性、方法、重载,反射在DLL中的使用方法
Unity数据加密☀️反射的用法:变量、属性、方法、重载,反射在DLL中的使用方法
|
3月前
|
C# 图形学 C语言
Unity3D学习笔记3——Unity Shader的初步使用
Unity3D学习笔记3——Unity Shader的初步使用
47 0
|
3月前
|
存储 Java 图形学
UNITY性能优化☀️一、GC介绍与Unity内存管理方法
UNITY性能优化☀️一、GC介绍与Unity内存管理方法
|
5月前
|
图形学 开发者
【Unity小技巧】unity移动物体的探究——使用8个不同方法
【Unity小技巧】unity移动物体的探究——使用8个不同方法
199 1