AndroidはNDKを使ってオンライン署名認証を行います.

14663 ワード

AndroidはNDKを使ってオンライン署名認証を行います.
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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!
"
); //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
Host:%s\r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r
User-Agent:%s\r
Accept-Language:%s\r
\r
"
; 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
0\r
"
; 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!
"
); // 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
\r
"
); 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("


tmpres Value:%d
"
,tmpres); } LOGI("receive data over!
"
); if(tmpres<0){ LOGI("Error receiving data!
"
); } 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(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(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();