openssl 설치기와 질문입니다. qt(mingw32) + window7(64bit)
windows7(64bit)
+ Qt Creator 2.1 Binary for Windows (46 MB)
+ Qt libraries 4.7.3 for Windows (minGW 4.4, 322 MB)
+ openssl-1.0.0d
위와 같은 환경에 openssl을 설치해 보았습니다..
일단 기본적인 동작은 하는데.. 문제도 있습니다..
----------
1. 원본소스로 openssl-1.0.0d는 제대로 빌드가 되지 않았다.
구글에서 "openssl-1.0.0d mingw32.bat" 라고 검색을 하니 patch파일을
http://rt.openssl.org/Ticket/Display.html?id=2474&user=guest&pass=guest 에서 찾을 수 있었다.
2. openssl-1.0.0d-mingw32-20110320.patch 파일들 다운로드 받아서
C:\develop\tools\openssl-1.0.0d\ 디렉토리에 복사함.
3. patch파일을 적용해야하는데, windows에서 관련 명령어(프로그램)가 없어서, cygwin에서 작업하기로함
# patch -p1 < openssl-1.0.0d-mingw32-20110320.patch
라고 명령을 하면 패치가 적용된다.
4. windows의 cmd창을 열어서,
C:\develop\tools\openssl-1.0.0d>ms\mingw32.bat
라고 명령하면 빌드가 됨
Generating the DLLs and input libraries
Done compiling OpenSSL
5. 빌드가 종료되면,
- C:\develop\tools\openssl-1.0.0d\outinc\openssl 디렉토리가 생성된다(여기엔 *.h파일들이 있음)
- C:\develop\tools\openssl-1.0.0d\ 에는 libeay32.dll, libssl32.dll 파일이 생긴다
- C:\develop\tools\openssl-1.0.0d\out 디렉토리가 생기고, libcrypto.a , libeay32.a , libssl.a , libssl32.a 및 많은 *.exe파일이 생긴다.
6.
- C:\develop\tools\openssl-1.0.0d\outinc\openssl 디렉토리를 통째로, C:\Qt\4.7.3\include\openssl 로 복사한다.
- libeay32.dll, libssl32.dll 파일을, C:\Qt\4.7.3\bin\ 으로 복사한다.
- libcrypto.a , libeay32.a , libssl.a , libssl32.a 파일을 C:\Qt\4.7.3\lib\ 으로 복사한다
-----------------------------------
테스트1.
main.cpp
#include <stdio.h> #include <string.h> #include <openssl/aes.h> int main(int argc, char *argv[]) { unsigned char plaintext[] = "Hello World!"; unsigned char key[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; unsigned char ciphertext[16]; unsigned char decryptedtext[16]; AES_KEY ekey, dkey; AES_set_encrypt_key(key,128,&ekey); AES_set_decrypt_key(key,128,&dkey); printf("Plain Text : %s\n",plaintext); AES_encrypt(plaintext, ciphertext,&ekey); printf("Ciphertext : "); for(int i=0 ; i<16 ; i++) printf("%02x",ciphertext[i]); printf("\n"); AES_decrypt(ciphertext, decryptedtext,&dkey); printf("Decryptedtext : %s \n",decryptedtext); return 0; }
opensslaes.pro
LIBS += -lcrypto CONFIG+=console SOURCES += main.cpp
결과
C:\c++qt_test\opensslaes-build-desktop\debug>opensslaes.exe Plain Text : Hello World! Ciphertext : ebb278425bfe07b9e9af0793ac1bf033 Decryptedtext : Hello World!
-----------------------------------
테스트2.
main.cpp
/** AES encryption/decryption demo program using OpenSSL EVP apis gcc -Wall openssl_aes.c -lcrypto this is public domain code. Saju Pillai (saju.pillai@gmail.com) **/ #include <string.h> #include <stdio.h> #include <stdlib.h> #include <openssl/evp.h> #include <openssl/aes.h> /** * Create an 256 bit key and IV using the supplied key_data. salt can be added for taste. * Fills in the encryption and decryption ctx objects and returns 0 on success **/ int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx, EVP_CIPHER_CTX *d_ctx) { int i, nrounds = 5; unsigned char key[32], iv[32]; /* * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. * nrounds is the number of times the we hash the material. More rounds are more secure but * slower. */ i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv); if (i != 32) { printf("Key size is %d bits - should be 256 bits\n", i); return -1; } EVP_CIPHER_CTX_init(e_ctx); EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); EVP_CIPHER_CTX_init(d_ctx); EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv); return 0; } /* * Encrypt *len bytes of data * All data going in & out is considered binary (unsigned char[]) */ unsigned char *aes_encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len) { /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ int c_len = *len + AES_BLOCK_SIZE, f_len = 0; unsigned char *ciphertext = (unsigned char *)malloc(c_len); /* allows reusing of 'e' for multiple encryption cycles */ EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL); /* update ciphertext, c_len is filled with the length of ciphertext generated, *len is the size of plaintext in bytes */ EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len); /* update ciphertext with the final remaining bytes */ EVP_EncryptFinal_ex(e, ciphertext+c_len, &f_len); *len = c_len + f_len; return ciphertext; } /* * Decrypt *len bytes of ciphertext */ unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len) { /* plaintext will always be equal to or lesser than length of ciphertext*/ int p_len = *len, f_len = 0; unsigned char *plaintext = (unsigned char *)malloc(p_len); EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL); EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len); EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len); *len = p_len + f_len; return plaintext; } int main(int argc, char **argv) { /* "opaque" encryption, decryption ctx structures that libcrypto uses to record status of enc/dec operations */ EVP_CIPHER_CTX en, de; /* 8 bytes to salt the key_data during key generation. This is an example of compiled in salt. We just read the bit pattern created by these two 4 byte integers on the stack as 64 bits of contigous salt material - ofcourse this only works if sizeof(int) >= 4 */ unsigned int salt[] = {12345, 54321}; unsigned char *key_data; int key_data_len, i; char *input[] = {"a", "abcd", "this is a test", "this is a bigger test", "\nWho are you ?\nI am the 'Doctor'.\n'Doctor' who ?\nPrecisely!", NULL}; /* the key_data is read from the argument list */ key_data = (unsigned char *)argv[1]; key_data_len = strlen(argv[1]); /* gen key and iv. init the cipher ctx object */ if (aes_init(key_data, key_data_len, (unsigned char *)&salt, &en, &de)) { printf("Couldn't initialize AES cipher\n"); return -1; } /* encrypt and decrypt each input string and compare with the original */ for (i = 0; input[i]; i++) { char *plaintext; unsigned char *ciphertext; int olen, len; /* The enc/dec functions deal with binary data and not C strings. strlen() will return length of the string without counting the '\0' string marker. We always pass in the marker byte to the encrypt/decrypt functions so that after decryption we end up with a legal C string */ olen = len = strlen(input[i])+1; ciphertext = aes_encrypt(&en, (unsigned char *)input[i], &len); plaintext = (char *)aes_decrypt(&de, ciphertext, &len); if (strncmp(plaintext, input[i], olen)) printf("FAIL: enc/dec failed for \"%s\"\n", input[i]); else printf("OK: enc/dec ok for \"%s\"\n", plaintext); free(ciphertext); free(plaintext); } EVP_CIPHER_CTX_cleanup(&en); EVP_CIPHER_CTX_cleanup(&de); return 0; }
결과 : 컴파일 오류
--------------------------------------------------------------------
질문
1. openssl 빌드 방법과, qt에 복사해서 적용하는 방법이 옳게 된건가요?
2. 첨부된 그림과 같은 오류의 원인은 어디서부터 찾아야 할까요?
첨부 | 파일 크기 |
---|---|
![]() | 154.37 KB |
이건 link error 인데요.
rand_win.c 에서 Windows API 를 호출하는 모양이네요. Windows API 를 위한 library link 가 필요하겠죠. user32, gdi32, kernel32 말입니다.
답변 감사합니다.
근데 잘 모르겠어요 ㅠㅠ
user32, gdi32, kernel32 를
#include <user32> 처럼 하라는 건가요?
조금만 더 도와주세요
굽신굽신 ㅠㅠ
Compile Output 에러나는 부분은 아래와 같습니다.
아마 console program이라 자동 link를 안하는 듯
http://msdn.microsoft.com/en-us/library/dd183489(VS.85).aspx 의 Requirements를 보세요.
제가 C++을 잘 몰라서 그러는데..
winner님이 말씀하시는건.. MS visual c++ 맞죠?
근데 저는 QT에서 하는건데... 서로 다른거 아닌가요?
아무튼.. 구글링을 통해서..
http://kangun.tistory.com/66 <- 이곳을 참고하여
openssl 소스중에서
# vim crypto/rand/rand_win.c 파일을
static void readscreen(void)
{
#if (0)
/*#if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN)*/
...
#endif
}
위처럼 수정해서 리빌드 한 다음에..
위의 프로그램을 다시 빌드해보니.. creatDCA, deleteDC 같은 오류는 뜨지 않네요.. (해결된듯..)
아직 확인해볼것이 많지만...
어쨌든... 휴~
암튼 답변 감사했습니다 꾸벅~
댓글 달기