티스토리 뷰
앱의 위변조를 방지하기 위하여 서명 값을 가져와서 서버에 미리 등록된 값과 비교하는 과정이 필요하다.
하지만, 안드로이드 Java 코드상으로 제공되는 API 를 활용하는 것은 안전하지 못하다.
(안드로이드 자바 코드상에서 서명 값 가져오기 : http://www.dev.re.kr/70)
그렇기 때문에 JNI 를 활용해야 한다. context 를 인자값으로 받아서 jni 에서 제공되는 리플렉션을 사용하여 SHA1 으로 변환된 서명 값을 가져오는 코드를 첨부한다.
주의할 점은 아래 코드는 C++ 로 작성되었기 때문에 C 에서 사용하려면 약간의 수정이 필요하다.
이를테면
env->GetObjectClass(context);
를 C로 표현 하려면
(*env)->GetObjectClass(env, context);
로 변환해야 한다.
스크롤바 때문에 코드를 보기 불편할 수 있으므로 파일도 추가한다.
// 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); }
'개발 관련 > Android ' 카테고리의 다른 글
[Tip] View 으로로부터 Bitmap 가져오기 :: getDrawingCache 를 호출했을 때 발생하는 문제 해결. (0) | 2015.05.08 |
---|---|
ActivityLifecycleCallbacks 를 이용하여 실행중인 Activity 상태와 객체 가져오기. (2) | 2015.04.09 |
안드로이드 APK 서명에 대하여 + java 코드상에서 APK 파일로부터 인증서 정보 가져오기. (3) | 2015.03.25 |
안드로이드 바이너리 XML 의 구조. (0) | 2015.03.23 |
Android NDK, JNI 내부에서 HTTP 통신 사용하기. (0) | 2015.03.20 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 블루투스
- HC-06
- Java
- Cheapduino
- bluetooth
- 부트로더
- 알리익스프레스
- 개발
- 아두이노
- 안드로이드
- ndk
- ESP8266
- 안드로이드 개발
- json
- ENC28J60
- WS2812B
- ATtiny85
- 이더넷
- 침블락
- oled
- noidemcu
- activity
- 병렬 프로그래밍
- 가습기
- 스마트 무드등
- 칩두이노
- arduino
- NeoPixel
- Android
- Iot
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함