AndroidStudio下JNI开发(easy+1.0)之签名

概述

根据前面的文章来看,JNI其实只实现了关键代码加密,如果别人拿到了你的Java Native方法定义和对应的so,即可完成对你so里方法的调。因为native 方法和类都是不能混淆的,混淆了方法的函数名就变了,调用的时候就找不到方法了,因此如果反编译APK可以非常容易拿到相关文件和代码。 显然我们需要一些手段来在JNI的验证请求接口的是不是我们的程序。

签名验证的原理

可以用如下图来表明加了验证之后调用JNI的逻辑,用一个isValid 来表明请求的应用是不是我们自己的应用。isValid 通过init 去初始化。 
这里写图片描述

如何判别调用者的有效性

直接有效的方案就是使用签名进行判定,如果你的keystore没有泄漏,第三方破解概率几乎为零。当然这都是相对的,任何防护都会有破绽。大多数第三方的Android SDK也都通过签名来判断申请的key是否用在了你申请的应用上。因此在大多数SDK申请key的时候会让你填写SHA1,因为在程序运行的时候SDK会获取你签名的SHA1去向服务器验证,你申请的appkey和SHA1是否正确。

签名验证的实现

在代码中获取签名的SHA1

先尝试在Java代码中获取签名的SHA1

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String <span class="hljs-title" style="box-sizing: border-box;">getCertSHA1</span>(Context context)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>
        {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取包管理器</span>
            PackageManager packageManager=context.getPackageManager();
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取包名</span>
            String packageName=context.getPackageName();
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获得包信息</span>
            PackageInfo   pis = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获得签名</span>
            Signature[] signs = pis.signatures; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//签名</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获得签名数组的第一位</span>
            Signature sign=signs[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获得X.509证书工厂</span>
            CertificateFactory certFactory = CertificateFactory.getInstance(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"X.509"</span>);

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] signBytes=sign.toByteArray();
            ByteArrayInputStream byteIn=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayInputStream(signBytes);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取X509证书</span>
            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(byteIn);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取证书发行者SHA1</span>
            MessageDigest sha1=MessageDigest.getInstance(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"SHA1"</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] certByte=cert.getEncoded();
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] bs=sha1.digest (certByte);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> toHex(bs);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (CertificateException e)
        {

            e.printStackTrace();
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e)
        {
            e.printStackTrace();
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将Byte转换成HexString 辅助函数</span>
     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[] cs=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>];
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;i++)
        {
            cs[i] = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>) (<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'0'</span> + i);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;i < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>;i++)
        {
            cs[i] = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>) (<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'A'</span> + i - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);
        }
    }
    String toHex(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] bs)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[] cs=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[bs.length * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i < bs.length;i++)
        {
            x = bs[i] & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff</span>;
            cs[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> * i] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.cs[x / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>];
            cs[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> * i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.cs[x % <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>];
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> String(cs);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li></ul>

这里使用的是debug.keystore 
LogCat输出: 
LogCat输出 
Keytool输出: 
控制台输出 
可以看到我们获取的SHA1是正确的。

注意:这里的signature只与签名时使用的证书有关系,这里生成的SHA1,也可以通过APK包中的CERT.RSA(解压APK之后,META-INF文件夹中)文件得到。 
CERT.RSA

在JNI中获取签名SHA1

我并没有在Android的C库中找到类似于PackageManager之类的东西,所以任然采用JNI的反射机制去调用相关的Java方法,其实就是将上面的Java方法翻译成C++代码。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Native 方法声明,显然这里需要传递一个Context过去用于获取包管理器以及包名</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">native</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">native_init</span>(Context context);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="language-C++ hljs scala has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//C++实现</span>
static bool is_valid= <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
const char *app_signature_sha1=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"40C438E3DAC29E04718E141BD816B3FC1A53E389"</span>;
const char HexCode[]={<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'0'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'1'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'2'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'3'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'4'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'5'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'6'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'7'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'8'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'9'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'A'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'B'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'C'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'D'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'E'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'F'</span>};
JNIEXPORT void JNICALL Java_com_wastrel_signtest_NativeFunc_native_1init
        (JNIEnv *env, j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">clz</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">jobject</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">context_object</span>){</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">context_class</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(context_object)</span>;</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//context.getPackageManager()</span>
    jmethodID methodId = env->GetMethodID(context_class, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getPackageManager"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"()Landroid/content/pm/PackageManager;"</span>);
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">package_manager_object</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CallObjectMethod</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(context_object, methodId)</span>;</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (package_manager_<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> == <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">NULL</span>) {</span>
       LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getPackageManager() Failed!"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//context.getPackageName()</span>
    methodId = env->GetMethodID(context_class, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getPackageName"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"()Ljava/lang/String;"</span>);
    jstring package_name_string = (jstring)env->CallObjectMethod(context_object, methodId);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (package_name_string == NULL) {
       LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getPackageName() Failed!"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ;
    }
    env->DeleteLocalRef(context_class);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//PackageManager.getPackageInfo(Sting, int)</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//public static final int GET_SIGNATURES= 0x00000040;</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">pack_manager_class</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(package_manager_object)</span>;</span>
    methodId = env->GetMethodID(pack_manager_class, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getPackageInfo"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"</span>);
    env->DeleteLocalRef(pack_manager_class);
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">package_info_object</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CallObjectMethod</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(package_manager_object, methodId, package_name_string, 0x40)</span>;</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (package_info_<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> == <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">NULL</span>) {</span>
        LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getPackageInfo() Failed!"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ;
    }
    env->DeleteLocalRef(package_manager_object);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//PackageInfo.signatures[0]</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">package_info_class</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(package_info_object)</span>;</span>
    jfieldID fieldId = env->GetFieldID(package_info_class, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"signatures"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"[Landroid/content/pm/Signature;"</span>);
    env->DeleteLocalRef(package_info_class);
    jobjectArray signature_object_array = (jobjectArray)env->GetObjectField(package_info_object, fieldId);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (signature_object_array == NULL) {
        LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"PackageInfo.signatures[] is null"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ;
    }
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">signature_object</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectArrayElement</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(signature_object_array, 0)</span>;</span>
    env->DeleteLocalRef(package_info_object);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Signature.toByteArray()</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">signature_class</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(signature_object)</span>;</span>
    methodId = env->GetMethodID(signature_class, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"toByteArray"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"()[B"</span>);
    env->DeleteLocalRef(signature_class);
    jbyteArray signature_byte = (jbyteArray) env->CallObjectMethod(signature_object, methodId);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//new ByteArrayInputStream</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">byte_array_input_class</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">FindClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"java/io/ByteArrayInputStream"</span>)</span>;</span>
    methodId=env->GetMethodID(byte_array_input_class,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<init>"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"([B)V"</span>);
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">byte_array_input</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">NewObject</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(byte_array_input_class,methodId,signature_byte)</span>;</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//CertificateFactory.getInstance("X.509")</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">certificate_factory_class</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">FindClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"java/security/cert/CertificateFactory"</span>)</span>;</span>
    methodId=env->GetStaticMethodID(certificate_factory_class,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getInstance"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"</span>);
    jstring x_509_jstring=env->NewStringUTF(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"X.509"</span>);
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">cert_factory</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CallStaticObjectMethod</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(certificate_factory_class,methodId,x_509_jstring)</span>;</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//certFactory.generateCertificate(byteIn);</span>
    methodId=env->GetMethodID(certificate_factory_class,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"generateCertificate"</span>,(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"</span>));
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">x509_cert</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CallObjectMethod</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(cert_factory,methodId,byte_array_input)</span>;</span>
    env->DeleteLocalRef(certificate_factory_class);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//cert.getEncoded()</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">x509_cert_class</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(x509_cert)</span>;</span>
    methodId=env->GetMethodID(x509_cert_class,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getEncoded"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"()[B"</span>);
    jbyteArray cert_byte=(jbyteArray)env->CallObjectMethod(x509_cert,methodId);
    env->DeleteLocalRef(x509_cert_class);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//MessageDigest.getInstance("SHA1")</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">message_digest_class</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">FindClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"java/security/MessageDigest"</span>)</span>;</span>
    methodId=env->GetStaticMethodID(message_digest_class,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getInstance"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(Ljava/lang/String;)Ljava/security/MessageDigest;"</span>);
    jstring sha1_jstring=env->NewStringUTF(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"SHA1"</span>);
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">sha1_digest</span>=<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CallStaticObjectMethod</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(message_digest_class,methodId,sha1_jstring)</span>;</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//sha1.digest (certByte)</span>
    methodId=env->GetMethodID(message_digest_class,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"digest"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"([B)[B"</span>);
    jbyteArray sha1_byte=(jbyteArray)env->CallObjectMethod(sha1_digest,methodId,cert_byte);
    env->DeleteLocalRef(message_digest_class);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//toHexString</span>
    jsize array_size=env->GetArrayLength(sha1_byte);
    jbyte* sha1 =env->GetByteArrayElements(sha1_byte,NULL);
    char *hex_sha=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> char[array_size*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (int i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i <array_size ; ++i) {
        hex_sha[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>*i]=HexCode[((unsigned char)sha1[i])/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>];
        hex_sha[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>*i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]=HexCode[((unsigned char)sha1[i])%<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>];
    }
    hex_sha[array_size*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\0'</span>;
    LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" %s "</span>,hex_sha);
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//比较签名</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (strcmp(hex_sha,app_signature_sha1)==<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)
    {
       LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"验证通过"</span>);
        is_valid= <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>{
        ThrowRuntimeExcption(env,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"验证失败"</span>);
    }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li></ul>

运行结果: 
运行结果

显然我们的结果达到了。在JNI中获得了签名的SHA1。验证通过之后isValid=true。别的JNIFunc调用的时候先判断一下isValid的值再操作即可。当应用签名和so里预置签名不一致时将无法获得正确结果。

其实代码不用这么长

从上面的Java代码或C++代码都可以看到,从CertificateFactory开始其实签名的元数据已经没有改变。因此其实我们不必大废周章的通过CertificateFactory 和MessageDigest两个类去求签名的SHA1值。其实直接比较元数据即可完成验证。那么我们如何获得签名的元数据呢?

  • 最简单的办法就是用发布的keystore签名APk,然后在Java代码中打印一次signature.toCharsString,然后从Logcat中拷贝出来。
  • 使用keytool工具提取。 
    • 使用命令keytool -list -rfc -keystore your.keystore。 
      命令结果
    • 拷贝-----BEGIN CERTIFICATE----------END CERTIFICATE-----之间的内容。很显然这是一段Base64,然后使用在线解码工具即可完成解码,注意要勾选结果使用16进制显示。 
      Base64解码
    • 去掉空格和\x等垃圾数据。

修改签名常量为获得的字符串:

<code class="language-C hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> *app_signature= <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"308201dd30820146020101300d06092a864886"</span>  <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"f70d010105050030373116301406035504030c0d416e64726f6964204465"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"6275673110300e060355040a0c07416e64726f6964310b30090603550406"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"13025553301e170d3136303732363134323834315a170d34363037313931"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"34323834315a30373116301406035504030c0d416e64726f696420446562"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"75673110300e060355040a0c07416e64726f6964310b3009060355040613"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"02555330819f300d06092a864886f70d010101050003818d003081890281"</span>    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"8100879fe1f34241cccb893c9a97fee78b89c74836086cd475145e32a2b37"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"dc149a2a141c5924aa877b8571defb43bfc0fa3182f5f888a7a063186af5"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"13a0afdd0a874c8d201656f6453bdb11e6fd2a3f59491c79399f3b73e611"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"cc0ddba58e30bdce9a12aaf63d298fb9c87675570a339e7fcf896edde5fb"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"b5236b6f6eff954e4330203010001300d06092a864886f70d01010505000"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"38181002f6cd4d87d190edd21964dcbdf0c5f27225737d85a9501f1601f7"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"d20dc00182504288871356383f7d4f01cc031c9a4faf395f210385aad0197"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"f98031e259ca69746f47768b077e9f0f965bc008b961fdd0747a2affa147f"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"707703123e1d0346e9f2f4fda391217a0fdeae4c1f842ccdfff4d346c74d"</span>
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"9e92b6f2c617c8cb4958f"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

然后修改C++方法中的//Signature.toByteArray()注释以下的内容:

<code class="language-C hljs mel has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    jclass signature_class = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">env</span>->GetObjectClass(signature_object);
    methodId = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">env</span>->GetMethodID(signature_class, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"toCharsString"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"()Ljava/lang/String;"</span>);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">env</span>->DeleteLocalRef(signature_class);
    jstring signature_jstirng = (jstring) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">env</span>->CallObjectMethod(signature_object, methodId);

    const  char <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*sign</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">env</span>->GetStringUTFChars(signature_jstirng,NULL); 
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strcmp</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sign</span>,app_signature)==<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)
    {
       LOGE(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"验证通过"</span>);
        is_valid= true;
    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>{
        ThrowRuntimeExcption(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">env</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"验证失败"</span>);
    }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

总结

libxxx.so认证,其实只是利用了Android签名的安全性来完成验证。本文大量从C++中调用了Java方法,包括静态方法,非晶态方法等等。

资源地址:http://download.csdn.net/detail/venusic/9615261

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值