AndroidはNDKを使ってオンライン署名認証を行います.
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();