티스토리 뷰


앱의 위변조를 방지하기 위하여 서명 값을 가져와서 서버에 미리 등록된 값과 비교하는 과정이 필요하다.

하지만, 안드로이드 Java 코드상으로 제공되는 API 를 활용하는 것은 안전하지 못하다.

(안드로이드 자바 코드상에서 서명 값 가져오기 : http://www.dev.re.kr/70)


그렇기 때문에 JNI 를 활용해야 한다. context 를 인자값으로 받아서 jni 에서 제공되는 리플렉션을 사용하여 SHA1 으로 변환된 서명 값을 가져오는 코드를 첨부한다. 


주의할 점은 아래 코드는 C++ 로 작성되었기 때문에 C 에서 사용하려면 약간의 수정이 필요하다. 

이를테면 


env->GetObjectClass(context);


를 C로 표현 하려면 


(*env)->GetObjectClass(env, context);


로 변환해야 한다.



스크롤바 때문에 코드를 보기 불편할 수 있으므로 파일도 추가한다.



getSignaiture.txt


// Context 를 인자값을 받아서 Signature 의 값을 얻는다.
char* getSignaiture(JNIEnv *env, jobject context) {
          jstring packageName;
          jobject packageManagerObj;
          jobject packageInfoObj;
          jclass contextClass =  env->GetObjectClass( context);
               jmethodID getPackageNameMid = env->GetMethodID( contextClass, "getPackageName", "()Ljava/lang/String;");
               jmethodID getPackageManager =  env->GetMethodID( contextClass, "getPackageManager", "()Landroid/content/pm/PackageManager;");

          jclass packageManagerClass = env->FindClass("android/content/pm/PackageManager");
               jmethodID getPackageInfo = env->GetMethodID( packageManagerClass, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");

          jclass packageInfoClass = env->FindClass("android/content/pm/PackageInfo");
               jfieldID signaturesFid = env->GetFieldID( packageInfoClass, "signatures", "[Landroid/content/pm/Signature;");

          jclass signatureClass = env->FindClass("android/content/pm/Signature");
               jmethodID signatureToByteArrayMid = env->GetMethodID( signatureClass, "toByteArray", "()[B");

          jclass messageDigestClass = env->FindClass("java/security/MessageDigest");
               jmethodID messageDigestUpdateMid = env->GetMethodID( messageDigestClass, "update", "([B)V");
               jmethodID getMessageDigestInstanceMid  = env->GetStaticMethodID( messageDigestClass, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
               jmethodID digestMid = env->GetMethodID( messageDigestClass,"digest", "()[B");

          jclass base64Class = env->FindClass("android/util/Base64");
               jmethodID encodeToStringMid = env->GetStaticMethodID( base64Class,"encodeToString", "([BI)Ljava/lang/String;");

          packageName =  (jstring)env->CallObjectMethod( context, getPackageNameMid);

          packageManagerObj = env->CallObjectMethod(context, getPackageManager);
          // PackageManager.GET_SIGNATURES = 0x40
          packageInfoObj = env->CallObjectMethod( packageManagerObj,getPackageInfo, packageName, 0x40);
          jobjectArray signatures = (jobjectArray)env->GetObjectField( packageInfoObj, signaturesFid);
          //int signatureLength =  env->GetArrayLength(signatures);
          jobject signatureObj = env->GetObjectArrayElement(signatures, 0);
          jobject messageDigestObj  = env->CallStaticObjectMethod(messageDigestClass, getMessageDigestInstanceMid, env->NewStringUTF("SHA1"));
          env->CallVoidMethod(messageDigestObj, messageDigestUpdateMid, env->CallObjectMethod( signatureObj,signatureToByteArrayMid));

          // Base64.DEFAULT = 0 그렇기 때문에 맨 마지막 인자값은 0이다.
          jstring signatureHash = (jstring)env->CallStaticObjectMethod( base64Class, encodeToStringMid,env->CallObjectMethod( messageDigestObj, digestMid, signatureObj), 0);

          return (char*)env->GetStringUTFChars(signatureHash,0);
}


댓글
  • 프로필사진 NDK개발 잘보고 갑니다. 다른값들도 가져올수 있나요? 예를들면 ADB 활성화 여부나 DDMS 활성화 여부, 에뮬레이터 동작 여부 등 안드로이드에서 제공하는것들 JNI로 가져올수 있나요? 2015.06.18 12:26 신고
  • 프로필사진 andy 안녕하세요.
    좋은 글 감사합니다.
    이번 프로젝트에서 똑 같은 요구를 받아서 고민하면서 찾던중 반가운 사이트를 알게되었읍니다.
    한가지 질문이 있어 메시지 남깁니다.
    저는 지금까지 JNI인터페이스시에는 항상 swig를 이용하여 랩퍼를 자동으로 생성하여 사용하고 있읍니다.
    그런데, swig에서 생성된 함수들은 항상 파라미터가 앞에서부터 JNIEnv *, jclass로 시작하여 사용자 지정 파라미터가 이어지고 있읍니다.
    하지만 올려진 글을 보면, 두번째 파라마터가 jobject로 되어있는데
    서로 다르게 사용되는 것인지, 아니면 동일하게 취급해도 되는 것인지 궁금합니다.
    감사합니다.
    2016.01.29 15:34 신고
  • 프로필사진 fff andy님 제가 글쓴이는 아니지만 jni 함수의 기본 프로토타입으로 두번째 인자는 jobject가 맞습니다. 2016.05.27 14:19 신고
  • 프로필사진 fff 정정합니다. 자바소스에서 native 함수를 static으로 정의했으면 두번째 인자가 jclass이고 아니면 jobject 입니다. 2016.07.18 09:37 신고
  • 프로필사진 비밀댓글입니다 2016.08.25 14:04
댓글쓰기 폼