标签:
在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