openssl 설치기와 질문입니다. qt(mingw32) + window7(64bit)

pogusm의 이미지

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. 첨부된 그림과 같은 오류의 원인은 어디서부터 찾아야 할까요?

File attachments: 
첨부파일 크기
Image icon qt_openssl_오류.JPG154.37 KB
winner의 이미지

rand_win.c 에서 Windows API 를 호출하는 모양이네요. Windows API 를 위한 library link 가 필요하겠죠. user32, gdi32, kernel32 말입니다.

pogusm의 이미지

근데 잘 모르겠어요 ㅠㅠ

user32, gdi32, kernel32 를

#include <user32> 처럼 하라는 건가요?

조금만 더 도와주세요

굽신굽신 ㅠㅠ

Compile Output 에러나는 부분은 아래와 같습니다.

g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-subsystem,console -mthreads -Wl -o debug\opensslaes03.exe debug/main.o  -L"c:\Qt\4.7.3\lib" -lcrypto -lQtGuid4 -lQtCored4 
mingw32-make[1]: Leaving directory `C:/Users/m/c++qt_test/opensslaes03-build-desktop'
mingw32-make: Leaving directory `C:/Users/m/c++qt_test/opensslaes03-build-desktop'
c:\Qt\4.7.3\lib/libcrypto.a(rand_win.o):rand_win.c:(.text+0xee0): undefined reference to `CreateDCA@16'
c:\Qt\4.7.3\lib/libcrypto.a(rand_win.o):rand_win.c:(.text+0xeef): undefined reference to `CreateCompatibleDC@4'
c:\Qt\4.7.3\lib/libcrypto.a(rand_win.o):rand_win.c:(.text+0xf08): undefined reference to `GetDeviceCaps@8'
....
winner의 이미지

http://msdn.microsoft.com/en-us/library/dd183489(VS.85).aspx 의 Requirements를 보세요.

pogusm의 이미지

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 같은 오류는 뜨지 않네요.. (해결된듯..)

아직 확인해볼것이 많지만...

어쨌든... 휴~

암튼 답변 감사했습니다 꾸벅~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.