Android使用NDK进行联网签名认证

4 篇文章 0 订阅
1 篇文章 0 订阅

Android使用NDK进行联网签名认证

#include <jni.h>
#include <string>
#include <android/log.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
extern "C"
{
#define HOST "127.0.0.1"
#define PAGE "/loc/keylist.do"
#define PORT 80
#define USERAGENT "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36"
#define ACCEPTLANGUAGE "zh-CN,zh;q=0.8,en;q=0.6,en-US;q=0.4,en-GB;q=0.2"
#define ACCEPTENCODING "gzip,deflate,sdch"

#define  LOG_TAG    "HelloJni"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
char* getServerKey(void);
char *jstringTostring(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("utf-8");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}

char *get_ip(const char *host){
    struct hostent *hent;
    int iplen=15;
    char *ip=(char *)malloc(iplen+1);
    memset(ip,0,iplen+1);
    if((hent=gethostbyname(host))==NULL){
      // perror("Can't get ip");
      //  exit(1);
        return NULL;
    }
    if(inet_ntop(AF_INET,(void *)hent->h_addr_list[0],ip,iplen)==NULL){
        LOGI("Can't resolve host!\n");
        //exit(1);
        return NULL;
    }
    return ip;
}
char *build_get_query(const char *host,const char *page){
    char *query;
    const char *getpage=page;
    const char *tpl="GET %s HTTP/1.1\r\nHost:%s\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nUser-Agent:%s\r\nAccept-Language:%s\r\n\r\n";
    query=(char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)+strlen(ACCEPTLANGUAGE)-5);//+strlen(ACCEPTENCODING)
    sprintf(query,tpl,getpage,host,USERAGENT,ACCEPTLANGUAGE);//ACCEPTENCODING
    return query;
}

char* getServerKey(void)
{
    const char* strend="\r\n0\r\n";
    std::string strcontent;
    struct sockaddr_in *remote;
    int sock;
    int tmpres;
    char* ip;
    char* get;
    const char* host;
    char buf[BUFSIZ+1];
    const char *page;
    if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        LOGI("socket create failed!");
        return NULL;
    }
    page=PAGE;
    host=HOST;
    ip=get_ip(host);
    if(ip== NULL){
        LOGI("ip is null");
        return NULL;
    }
    remote=(struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
    remote->sin_family=AF_INET;
    tmpres=inet_pton(AF_INET,ip,(void *)(&(remote->sin_addr.s_addr)));
    remote->sin_port=htons(PORT);
    if(connect(sock,(struct sockaddr *)remote,sizeof(struct sockaddr))<0){
        LOGI("Could not connect!\n");
       // exit(1);
        return NULL;
    }
    get =build_get_query(host,page);

    int sent=0;
    while(sent<strlen(get)){
        tmpres=send(sock,get+sent,strlen(get)-sent,0);
        if(tmpres==-1){
            LOGI("Can't send query!");
          //  exit(1);
            return NULL;
        }
        sent+=tmpres;
    }
    memset(buf,0,sizeof(buf));
    int htmlstart=0;
    char *htmlcontent;
    while((tmpres=recv(sock,buf,BUFSIZ,0))>0){
        if(htmlstart==0){
            htmlcontent=strstr(buf,"\r\n\r\n");
            if(htmlcontent!=NULL){
                htmlstart=1;
                htmlcontent+=4;
            }
        }else{
            htmlcontent=buf;
        }
      if(htmlstart){
          LOGI("start receive");
          strcontent+=std::string(htmlcontent);
//这个地方不完善  不完善 不完善  不完善  不完善   没去对CHUNKED编码解析   如果是content length  需要去比对长度 手动断掉TCP连接不然recv会阻塞 ,这个只是个demo不完善
          if( strstr(strcontent.c_str(),strend))
          {
              break;
          }
        }
        LOGI("%s",buf);
        memset(buf,0,tmpres);
        LOGI("\n\n\ntmpres Value:%d\n",tmpres);
    }
    LOGI("receive data over!\n");
    if(tmpres<0){
        LOGI("Error receiving data!\n");
    }
    free(get);
    free(remote);
    free(ip);
    close(sock);
    LOGI("content size:%d",strcontent.size());
    //int pos=strcontent.find(strend);
    //if(pos>=0)
     //   strcontent.erase((pos,strlen(strend)));
    return (char*)strcontent.c_str();
}

bool CourseKeyIsVail(JNIEnv *env, jobject contextObject, const char *key) {
        jclass native_class = env->GetObjectClass(contextObject);
        jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager",
                                           "()Landroid/content/pm/PackageManager;");
        jobject pm_obj = env->CallObjectMethod(contextObject, pm_id);
        jclass pm_clazz = env->GetObjectClass(pm_obj);
        jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo",
                                                     "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
        jclass native_classs = env->GetObjectClass(contextObject);
        jmethodID mId = env->GetMethodID(native_classs, "getPackageName", "()Ljava/lang/String;");
        jstring pkg_str = static_cast<jstring>(env->CallObjectMethod(contextObject, mId));
        jobject pi_obj = env->CallObjectMethod(pm_obj, package_info_id, pkg_str, 64);// 获得应用包的信息
        jclass pi_clazz = env->GetObjectClass(pi_obj);// 获得 PackageInfo 类
        jfieldID signatures_fieldId = env->GetFieldID(pi_clazz, "signatures",
                                                      "[Landroid/content/pm/Signature;");// 获得签名数组属性的 ID
        jobject signatures_obj = env->GetObjectField(pi_obj, signatures_fieldId);
        jobjectArray signaturesArray = (jobjectArray) signatures_obj;
        jsize size = env->GetArrayLength(signaturesArray);
        jobject signature_obj = env->GetObjectArrayElement(signaturesArray, 0);
        jclass signature_clazz = env->GetObjectClass(signature_obj);
        jmethodID string_id = env->GetMethodID(signature_clazz, "toCharsString",
                                               "()Ljava/lang/String;");
        jstring str = static_cast<jstring>(env->CallObjectMethod(signature_obj, string_id));
        char *c_msg = (char *) env->GetStringUTFChars(str, 0);
        if(strcmp(c_msg,key)==0)
            return true;
        else
            return false;
    }
}

使用方法

JNIEXPORT
jboolean
Java_com_xxx_xxx_xxx_xxx_KeyIsVail(JNIEnv *env, jobject contextObject)
{
    if (CourseKeyIsVail(env,contextObject,getServerKey()))
        return 1;
    else
        return 0;
}

Java层的代码是  public native boolean KeyIsVail();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值