본문 바로가기
프로그래밍/Android

how to use so files in Android JNI -2-

by 즉흥 2016. 8. 3.
728x90
반응형


1부 : http://amgn.tistory.com/600



환경


운영체제 : Windows 10

IDE : Android Studio

예제 so 파일 : OpenSSL



2부에서는 OpenSSL을 이용한 암호화와 so 파일에 저장된 함수 혹은 메소드를 가져와서 사용하는 방법에 대해 알아보도록 하겠다.



1. 사전 작업


후..


Openssl을 빌드 한 번에 안드로이드용으로 만들 수 없어서 사전 작업이 어마어마하게 많다.


물론 github에 안드로이드 용으로 나와서 nkd-build만 하면 되는 코드들도 많고 하지만


역시나 누군가 미리 prebuilt 버전을 github에 올려놓았다.


내가 시발 며칠 동안 개고생했는데 이런게 있었다.


후 ㅅㅂ


https://github.com/emileb/OpenSSL-for-Android-Prebuilt


https://github.com/felipejfc/openssl_prebuilt_for_android


둘 중 아무거나 다운 받아서 쓰면 된다.


참고로 위 링크에는 .so와 .a가 둘 다 있는 반면에 아래 링크에는 .a밖에 없다.


OpenSSL-for-Android-Prebuilt-master.zip

openssl_prebuilt_for_android-master.zip


일단 github에 있는거 둘 다 업로드 해본다.


내가 .a를 Android Studio에서 써보려고 별 ㅈㄹ을 다 해봤는데 도저히 못하는 바람에 나는 .so로 코딩을 하였다.


.a 사용하는 방법 알면 좀 알려주길 바람.


아.. 어차피 안드로이드 코딩도 아마 이걸로 끝이니까 필요 없으려나.



OpenSSL so 파일을 사용하기 위해 1부에서 했던 작업에 이어 추가적인 작업이 필요하다.


우선 build.gradle을 수정한다.


1
2
3
4
5
ndk{
    moduleName "testLib"
    stl "stlport_static"
    ldLibs "log""dl"
}
cs


stl "stlport_static"은 JNI에서 C++ STL을 사용하기 위해 추가하는 것이고,


ldLibs에 "log"는 아래에 따로 설명할 log 출력을 위해, "dl"은 이것도 아래에 따로 설명할 dlopen, dlsym 등의 함수를 사용하기 위해 사용하는 라이브러리이다.




그리고 /src/main/jniLibs 디렉토리를 생성하여 아래 사전처럼 .so 파일을 넣어준다.


자세한건 모르고 확실한 정보도 아니지만 gradle이 위 경로를 참조하여 외부 라이브러리 파일(.so, .a)을 읽는다고 한다.



Android Studio에서 모듈이나 리얼 머신에서 돌리기만 할꺼면 여기까지만 해도 되고,


ndk-build를 해주고 싶다면 Android.mk와 Application.mk를 조금 수정해주어야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := ../jniLibs/$(TARGET_ARCH_ABI)/libcrypto.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
include $(CLEAR_VARS)
LOCAL_MODULE := openssl
LOCAL_SRC_FILES := ../jniLibs/$(TARGET_ARCH_ABI)/libssl.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
 
include $(CLEAR_VARS)
LOCAL_MODULE := kyLib
LOCAL_SRC_FILES := kyFuncs.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS += -ldl
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/openssl
LOCAL_SHARED_LIBRARIES += crypto
LOCAL_SHARED_LIBRARIES += openssl
include $(BUILD_SHARED_LIBRARY)
cs

△ Android.mk




1
2
APP_ABI := armeabi, x86, armeabi-v7a
APP_STL := stlport_static
cs

△ Application.mk



별도의 설명을 필요 없을 것이다.




2. .so 파일에서 함수 가져오기


설명은 아래의 예제와 링크로 대체한다.


http://linux.die.net/man/3/dlerror


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
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
 
int
main(int argc, char **argv)
{
    void *handle;
    double (*cosine)(double);
    char *error;
 
   handle = dlopen("libm.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }
 
   dlerror();    /* Clear any existing error */
 
   /* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
       would seem more natural, but the C99 standard leaves
       casting from "void *" to a function pointer undefined.
       The assignment used below is the POSIX.1-2003 (Technical
       Corrigendum 1) workaround; see the Rationale for the
       POSIX specification of dlsym(). */
 
   *(void **) (&cosine) = dlsym(handle, "cos");
 
   if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }
 
   printf("%f\n", (*cosine)(2.0));
    dlclose(handle);
    exit(EXIT_SUCCESS);
}
cs


1
2
3
4
typedef void (*def_SSL_load_error_strings)(void);
def_SSL_load_error_strings my_SSL_load_error_strings = (def_SSL_load_error_strings)dlsym(handle, "SSL_load_error_strings");
if(my_SSL_load_error_strings == NULL)
    return 0;
cs


이런 식으로 사용하면 된다.




3. 에러 로그 출력하기


1
2
3
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , "libnav", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "libnav", __VA_ARGS__)
cs


JNI 디버깅 방법을 몰라서 ㅈㄴ 불편했는데 그 대안책으로 에러 로그를 출력해 보는 방법이 있다.


LOGI(str); 으로 쓰면 되고 포맷 스트링이 가능하여 편리하다.

LOG("%s", str_c_str());



4. string Converting


1
2
3
4
5
6
7
//Convert jstring to C++ string
const char *msg = env->GetStringUTFChars(jstr, JNI_FALSE);
    //after use
env->ReleaseStringUTFChars(jstr, msg);
 
//Convert C++ string jstring
jstring ret = env->NewStringUTF(buf);
cs

간단한 함수들이지만 알면 편한다.




5. base64


출처 : http://devsw.tistory.com/127


많은 사이트와 코드를 봤는데 이 코드가 openssl과 C++ STL을 이용해 가장 깔끔한 코드인 것 같다.



아래는 인코딩 코드.

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
#include "openssl/buffer.h"
#include "openssl/bio.h"
#include "openssl/evp.h"
#include "openssl/ossl_typ.h"
 
void base64e(std::string& arg)
{
    const char *input = arg.c_str();
    int length = arg.length();
 
    BIO *bmem, *b64;
    BUF_MEM *bptr;
 
    b64 = BIO_new(BIO_f_base64());
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, input, length);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);
 
    char *buffer = (char *)malloc(bptr->length);
    memcpy(buffer, bptr->data, bptr->length-1);
    buffer[bptr->length-1= 0;
 
    BIO_free_all(b64);
    arg = buffer;
 
    free(buffer);
    buffer = NULL;
}
cs


아래는 디코딩 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "openssl/buffer.h"
#include "openssl/bio.h"
#include "openssl/evp.h"
#include "openssl/ossl_typ.h"
 
void base64d(std::string& arg)
{
    const char *input = arg.c_str();
    int length = arg.length();
 
    char *buffer = (char *)malloc(length);
    memset(buffer, 0, length);
 
    BIO *bmem = BIO_new_mem_buf((void*)input, length);
    BIO *bioCmd = BIO_new(BIO_f_base64());
    BIO_set_flags(bioCmd, BIO_FLAGS_BASE64_NO_NL);
    bmem = BIO_push(bioCmd, bmem);
 
    BIO_read(bmem, (void *)buffer, length);
 
    arg = buffer;
}
cs



된다 ㅎ


1
2
3
08-07 13:00:53.673 5431-5431/com.example.test.myapplication I/libnav: ### plainttext : test
08-07 13:00:53.673 5431-5431/com.example.test.myapplication I/libnav: ### encrpyt : dGVzdA==
08-07 13:00:53.674 5431-5431/com.example.test.myapplication I/libnav: ### decrpyt : test
cs

로그를 통해 중간 중간에 std::string tmp에 어떠한 값이 들어갔는지 확인할 수 있다.






6. RSA


출처 : http://hayageek.com/rsa-encryption-decryption-openssl-c/


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
 
int padding = RSA_PKCS1_PADDING;
 
RSA * createRSA(unsigned char * key,int public)
{
    RSA *rsa= NULL;
    BIO *keybio ;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio==NULL)
    {
        printf"Failed to create key BIO");
        return 0;
    }
    if(public)
    {
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULLNULL);
    }
    else
    {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULLNULL);
    }
    if(rsa == NULL)
    {
        printf"Failed to create RSA");
    }
 
    return rsa;
}
 
int public_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,1);
    int result = RSA_public_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}
int private_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,0);
    int  result = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}
 
 
int private_encrypt(unsigned char * data,int data_len,unsigned char * key, unsigned char *encrypted)
{
    RSA * rsa = createRSA(key,0);
    int result = RSA_private_encrypt(data_len,data,encrypted,rsa,padding);
    return result;
}
int public_decrypt(unsigned char * enc_data,int data_len,unsigned char * key, unsigned char *decrypted)
{
    RSA * rsa = createRSA(key,1);
    int  result = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);
    return result;
}
 
void printLastError(char *msg)
{
    char * err = malloc(130);;
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    printf("%s ERROR: %s\n",msg, err);
    free(err);
}
 
int main(){
 
  char plainText[2048/8= "Hello this is Ravi"//key length : 2048
 
 char publicKey[]="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
  
 char privateKey[]="-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy\n"\
"vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9\n"\
"Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9\n"\
"yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l\n"\
"WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q\n"\
"gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8\n"\
"omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e\n"\
"N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG\n"\
"X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd\n"\
"gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl\n"\
"vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF\n"\
"1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu\n"\
"m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ\n"\
"uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D\n"\
"JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D\n"\
"4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV\n"\
"WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5\n"\
"nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG\n"\
"PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA\n"\
"SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1\n"\
"I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96\n"\
"ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF\n"\
"yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5\n"\
"w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX\n"\
"uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw\n"\
"-----END RSA PRIVATE KEY-----\n";
 
    
unsigned char  encrypted[4098]={};
unsigned char decrypted[4098]={};
 
int encrypted_length= public_encrypt(plainText,strlen(plainText),publicKey,encrypted);
if(encrypted_length == -1)
{
    printLastError("Public Encrypt failed ");
    exit(0);
}
printf("Encrypted length =%d\n",encrypted_length);
 
int decrypted_length = private_decrypt(encrypted,encrypted_length,privateKey, decrypted);
if(decrypted_length == -1)
{
    printLastError("Private Decrypt failed ");
    exit(0);
}
printf("Decrypted Text =%s\n",decrypted);
printf("Decrypted Length =%d\n",decrypted_length);
 
 
encrypted_length= private_encrypt(plainText,strlen(plainText),privateKey,encrypted);
if(encrypted_length == -1)
{
    printLastError("Private Encrypt failed");
    exit(0);
}
printf("Encrypted length =%d\n",encrypted_length);
 
decrypted_length = public_decrypt(encrypted,encrypted_length,publicKey, decrypted);
if(decrypted_length == -1)
{
    printLastError("Public Decrypt failed");
    exit(0);
}
printf("Decrypted Text =%s\n",decrypted);
printf("Decrypted Length =%d\n",decrypted_length);
 
}
cs


위 코드에서 printf를 LOGI로 바꿔서 확인해 보면 아래와 같다.

1
2
3
4
5
6
7
8
08-07 16:07:55.960 4403-4403/com.example.test.myapplication I/libnav: Encrypted length =256
08-07 16:07:55.974 4403-4403/com.example.test.myapplication I/libnav: Decrypted Text =Hello this is Ravi
08-07 16:07:55.974 4403-4403/com.example.test.myapplication I/libnav: Decrypted Length =18
08-07 16:07:55.988 4403-4403/com.example.test.myapplication I/libnav: Encrypted length =256
08-07 16:07:55.991 4403-4403/com.example.test.myapplication I/libnav: Decrypted Text =Hello this is Ravi
08-07 16:07:55.991 4403-4403/com.example.test.myapplication I/libnav: Decrypted Length =18
08-07 16:07:55.991 4403-4403/com.example.test.myapplication I/libnav: ### plainttext : base 64 test
08-07 16:07:55.993 4403-4403/com.example.test.myapplication I/libnav: ### encrpyt : YmFzZSA2NCB0ZXN0
cs




7. 소켓 통신


암호화 과정이 끝났으니 이제 마지막..


SSL(Secure Socket Layer)


소켓 통신 과정이 남았다.


https://www.cs.utah.edu/~swalton/listings/articles/ssl_client.c


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* ssl_client.c
 *
 * Copyright (c) 2000 Sean Walton and Macmillan Publishers.  Use may be in
 * whole or in part in accordance to the General Public License (GPL).
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
*/
 
/*****************************************************************************/
/*** ssl_client.c                                                          ***/
/***                                                                       ***/
/*** Demonstrate an SSL client.                                            ***/
/*****************************************************************************/
 
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
 
#define FAIL    -1
 
/*---------------------------------------------------------------------*/
/*--- OpenConnection - create socket and connect to server.         ---*/
/*---------------------------------------------------------------------*/
int OpenConnection(const char *hostname, int port)
{   int sd;
    struct hostent *host;
    struct sockaddr_in addr;
 
    if ( (host = gethostbyname(hostname)) == NULL )
    {
        perror(hostname);
        abort();
    }
    sd = socket(PF_INET, SOCK_STREAM, 0);
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = *(long*)(host->h_addr);
    if ( connect(sd, &addr, sizeof(addr)) != 0 )
    {
        close(sd);
        perror(hostname);
        abort();
    }
    return sd;
}
 
/*---------------------------------------------------------------------*/
/*--- InitCTX - initialize the SSL engine.                          ---*/
/*---------------------------------------------------------------------*/
SSL_CTX* InitCTX(void)
{   SSL_METHOD *method;
    SSL_CTX *ctx;
 
    OpenSSL_add_all_algorithms();        /* Load cryptos, et.al. */
    SSL_load_error_strings();            /* Bring in and register error messages */
    method = SSLv2_client_method();        /* Create new client-method instance */
    ctx = SSL_CTX_new(method);            /* Create new context */
    if ( ctx == NULL )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}
 
/*---------------------------------------------------------------------*/
/*--- ShowCerts - print out the certificates.                       ---*/
/*---------------------------------------------------------------------*/
void ShowCerts(SSL* ssl)
{   X509 *cert;
    char *line;
 
    cert = SSL_get_peer_certificate(ssl);    /* get the server's certificate */
    if ( cert != NULL )
    {
        printf("Server certificates:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 00);
        printf("Subject: %s\n", line);
        free(line);                            /* free the malloc'ed string */
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 00);
        printf("Issuer: %s\n", line);
        free(line);                            /* free the malloc'ed string */
        X509_free(cert);                    /* free the malloc'ed certificate copy */
    }
    else
        printf("No certificates.\n");
}
 
/*---------------------------------------------------------------------*/
/*--- main - create SSL context and connect                         ---*/
/*---------------------------------------------------------------------*/
int main(int count, char *strings[])
{   SSL_CTX *ctx;
    int server;
    SSL *ssl;
    char buf[1024];
    int bytes;
    char *hostname, *portnum;
 
    if ( count != 3 )
    {
        printf("usage: %s <hostname> <portnum>\n", strings[0]);
        exit(0);
    }
    hostname=strings[1];
    portnum=strings[2];
 
    ctx = InitCTX();
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);                        /* create new SSL connection state */
    SSL_set_fd(ssl, server);                /* attach the socket descriptor */
    if ( SSL_connect(ssl) == FAIL )            /* perform the connection */
        ERR_print_errors_fp(stderr);
    else
    {   char *msg = "Hello???";
 
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        ShowCerts(ssl);                                /* get any certs */
        SSL_write(ssl, msg, strlen(msg));            /* encrypt & send message */
        bytes = SSL_read(ssl, buf, sizeof(buf));    /* get reply & decrypt */
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);                                /* release connection state */
    }
    close(server);                                    /* close socket */
    SSL_CTX_free(ctx);                                /* release context */
}
cs


메니페스트에


1
2
3
<manifest ...
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest
cs


추가


코딩을 다 하고 나면 서버로부터 아래와 같은 결과를 받을 수 있다.


1
2
3
4
5
08-08 07:41:00.725 2671-2671/com.example.test.myapplication I/libnav: Connected with AES256-SHA encryption
08-08 07:41:00.725 2671-2671/com.example.test.myapplication I/libnav: Server certificates:
08-08 07:41:00.725 2671-2671/com.example.test.myapplication I/libnav: Subject: (null)
08-08 07:41:00.725 2671-2671/com.example.test.myapplication I/libnav: Issuer: (null)
08-08 07:41:00.738 2671-2671/com.example.test.myapplication I/libnav: Received: "hello!"
cs


그리고 아래는 서버에서 나오는 화면이다.




서버는 각자 특기 언어로 알아서 짜길 바람.



::Communicate() 함수를 통해 인자로 받는 String은 서버로 전달하고, 서버에서 보내는 String은 반환하도록 ::Communicate() 함수를 만들어 보았다.



굳.


하.. 안드로이드 코딩, java 등 기본 배경지식이 없는 상황에서 거의 1주일 동안 개삽질 하면서 끝냈다.


중간 중간에 삽질하면서 프로젝트도 새로 만들고, 함수 이름도 바꾸고 그래서 그대로 따라한다면 헷갈릴 수도 있겠지만 이름이야 끼워맞추면 되니까 큰 어려움이 없을 것으로 보인다.


=================================================


전부 작업하고 나서 알게 되었는데 내가 여태까지 사용하던 gradle은 2.4 이전 버전에서 사용하던 문법이라 한다..


어쩐지 stackoverflow나 github 등에서 예제라고 올라오던 gradle과는 다르더라..


gradle 2.4 버전부터 크게 바뀜..


자세한건 https://github.com/googlesamples/android-ndk 을 참조하고, 사실 2.4 이전처럼 사용해도 큰 상관은 없음.


근데 앞으로 인터넷 상에 QnA가 2.4 이후로 나올테니 .. 일단 참고해두자.



아마.. 안드로이드 코딩은 이제 안 할 것 같지만..

728x90
반응형

댓글