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 같은 오류는 뜨지 않네요.. (해결된듯..)
아직 확인해볼것이 많지만...
어쨌든... 휴~
암튼 답변 감사했습니다 꾸벅~
댓글 달기