GSI

퍼온글 주소 : http://www.debuglab.com/knowledge/dataencrypt.html

-내용-
dwDataLen = strPassword.GetLength();
CopyMemory(lpData, (LPVOID)(LPCTSTR)strPassword, strPassword.GetLength());

// 암호화
CCrypt Crypt;
Crypt.Create((LPBYTE)(LPCTSTR)strPassword, strPassword.GetLength());
Crypt.Encrypt(lpData, dwDataLen);
Crypt.Destroy();

// 암호화된 데이터 해독
Crypt.Create((LPBYTE)(LPCTSTR)strPassword, strPassword.GetLength());
Crypt.Decrypt(lpData, dwDataLen);
lpData[dwDataLen] = '\0';
::MessageBox(NULL, (LPCTSTR)lpData, "", MB_OK);

소스코드 :





.
Posted by gsi
:

데이터 암호화 방법

1.요약
데이터를 암호화하는 방법에는 여러가지가 있는데 가장 간단한 방법이 배타적 논리합(Exclusive OR)를 이용하는 방법이 있습니다.

이 방법은 너무 간단해서 보안에 치명적이죠. 특별한 암호방법을 고안해낼려면 그쪽 분야에 많은 연구와 노력이 필요한데 저를 포함해 대부분 암호화에 대한 지식이 거의 전무할겁니다.

저같은 사람들을 위해 MS에서 암호화를 위한 API를 제공하고 있습니다.
하지만 이것도 사용하기가 너무 복잡하고 여러 단계를 거져야하는 불편함이 있습니다.

그래서 최대한 사용하기 간단하게 Class로 만들어 보았습니다.


2.본문

먼저 암호에 필요한 API함수는 어떤것이 있는지 알아보겠습니다.
BOOL WINAPI CryptAcquireContext(HCRYPTPROV *phProv, LPCTSTR Container,
                LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags);

BOOL WINAPI CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid,
                CRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash);

BOOL WINAPI CryptHashData(HCRYPTHASH hHash, BYTE *pbData,
                DWORD dwDataLen, DWORD dwFlags);

BOOL WINAPI CryptDeriveKey(HCRYPTPROV hProv, ALG_ID Algid,
                HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey);

BOOL WINAPI CryptEncrypt(HCRYPTKEY hKey, HCRYPTHASH hHash,
                BOOL Final, DWORD dwFlags, BYTE *pbData,
                DWORD *pdwDataLen, DWORD dwBufLen);

BOOL WINAPI CryptDecrypt(HCRYPTKEY hKey, HCRYPTHASH hHash,
                BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen);
자세한 사용법은 MSDN을 참고하세요.
이러한 API의 사용법을 설명하지 않겠습니다. 사실 저도 자세히는 모름니다. Class 멤버 함수와 사용법을 소개드리겠습니다.

BOOL CCrypt::Create(LPBYTE pHashData, DWORD dwHashDataLen)
- 암호화나 해독에 필요한 Key를 생성하는 함수. 쉽게 여기에 Password가 들어간다고 생각하면 됩니다.
void CCrypt::Destroy()
- Create에서 만들어진 Handle을 제거합니다.
BOOL CCrypt::Encrypt(LPBYTE lpBuffer, DWORD& dwBufferLen, BOOL bFanal)
- 데이터를 암호화하는 함수
BOOL CCrypt::Decrypt(LPBYTE lpBuffer, DWORD& dwBufferLen, BOOL bFanal)
- 암호화된 데이터를 해독하는 함수

3.예제

dwDataLen = strPassword.GetLength(); 
CopyMemory(lpData, (LPVOID)(LPCTSTR)strPassword, strPassword.GetLength()); 

// 암호화 
CCrypt Crypt; 
Crypt.Create((LPBYTE)(LPCTSTR)strPassword, strPassword.GetLength()); 
Crypt.Encrypt(lpData, dwDataLen); 
Crypt.Destroy(); 

// 암호화된 데이터 해독 
Crypt.Create((LPBYTE)(LPCTSTR)strPassword, strPassword.GetLength()); 
Crypt.Decrypt(lpData, dwDataLen); 
lpData[dwDataLen] = '\0'; 

::MessageBox(NULL, (LPCTSTR)lpData, "", MB_OK);
Crypt.zip 다운로드

















- 2001.08.19 Smile Seo -



http://www.debuglab.com/knowledge/dataencrypt.html

Posted by gsi
:

아래의 코드는 내가 정신없이 한줄을 작성하면서 생긴 일이다.
참으로 어이가 없는 경우이긴 하지만 발생할 수 있는 상태가 된 나로서는
아무래도 헤롱헤롱 하는 상태인듯 하다.

d:\NG_Project\Project\NGTools\NGMakerShop080\NGMakerShop080_Work\DataMgr\NGBObject.h(70): error C2039: 'first' : is not a member of 'std::_Tree<_Traits>::iterator'
        with
        [
            _Traits=std::_Tmap_traits<int,int,std::less<int>,std::allocator<std::pair<const int,int>>,false>
        ]

문제가된 코드

  map< int, int> m_test;
  m_test[10] = 10;
  map< int, int>::iterator iter = m_test.begin();
  int aaa = iter.first; //<--여기..

이 코드를 보고도 어디가 문제인지 모르는 분은 나랑 비슷한 상태인듯 하다 ^^

이 코드는 아래와 같이 되어야 한다.

int aaa = (*iter).first;

앞으로는 조금더 정신 차리고 해야 할거 같다.

Posted by gsi
:

stl string trim 구현하기

STL 2007. 9. 6. 14:43 |

string을 사용하고 있지만.. trim이 없는듯 합니다. -.- 혹시 알면 댓글.. 부탁 드림..

아래와 같은 프로그램 경로가 있다고 햇을때 프로그램 파일 부분만 잘라 낼려고 할대
아래와 같은 코드를 사용했습니다.

원본 패스 : d:\gsi_project\projectx\bin\AttachImageMakerd.exe
결과 패스 : d:\gsi_project\projectx\bin

//초기화

string appPath = argv[0];
string appdir;
appdir.clear();
//뒷 부분을 잘라 내야 하기 때문에 우선 뒤쪽에서 '\'를 찾는다.

int findidx = (int)appPath.rfind('\\');

//찾은 인덱스를 사용해서 잘라낸다.

appdir = string(appPath, 0, findidx); //appPath : 풀 패스, 0 : 시작인덱스, findidx : 끝 인덱스

이상...

Posted by gsi
:

float, int 등을 string 변환 - ostringstream 이용

#include <sstream>

std::ostringstream outstream;
outstream << 숫자등등
std::string str = outstream .str()

Posted by gsi
:

for_each()를 사용할때

//클래스

class Widget {
public:
 Widget(int var) : value(var) {}

 void Test() {
  cout << "값 " << value << endl;
 }

public:
 int value;
};

//함수 선언

void Test(Widget& w)
{
 cout << w.value << endl;
}

//사용하는곳

 vector<Widget> vw;

 vw.push_back(Widget(1));
 vw.push_back(Widget(2));
 vw.push_back(Widget(3));
 vw.push_back(Widget(4));
 vw.push_back(Widget(5));

//일반 함수는 Test 또는 ptr_fun(Test) 라고 하면 됩니다.

 for_each(vw.begin(), vw.end(), Test);
 for_each(vw.begin(), vw.end(), ptr_fun(Test));

//클래스 내부의 함수를 접근 할 때는 vw의 형태가 참조냐 포인터냐에 따라서

//달라 집니다. 참조 이기 때문에 mem_fun_ref(&Widget::Test)를 사용합니다.
 for_each(vw.begin(), vw.end(), mem_fun_ref(&Widget::Test));

 vector<Widget*> lpw;

 lpw.push_back(new Widget(1));
 lpw.push_back(new Widget(2));
 lpw.push_back(new Widget(3));
 lpw.push_back(new Widget(4));
 lpw.push_back(new Widget(5));

//포인터이기 때문에 mem_fun(&Widget::Test)를 사용하게 되지요.

 for_each(lpw.begin(), lpw.end(), mem_fun(&Widget::Test));

Posted by gsi
:

vector <> 에 포인터 객체를 넣게 되면 많은 부분 불편한게 생긴다.
메모리의 삭제에 있어서 다른 처리를 해야 하기 때문이다.

하지만 boost의 shared_ptr를 사용하면 아주 편하게 구현이 됩니다.
관련 내용 : http://crowmania.cafe24.com/crowmania/?p=50

[헤더]
#include <vector>
using namespace std;
#include <boost/shared_ptr.hpp>

//테스트할 클래스 구성
class CMemTest
{
public:
 CMemTest() : _val(0)
 {
 }
 CMemTest(int val)
 {
  _val = val;
 }
 ~CMemTest()
 {
 
 }

 int _val;
};

//부스터에 맞는 타입디파인
typedef boost::shared_ptr<CMemTest> SPMemTest;

[코드]
vector<SPMemTest> m_SPMemTest;

SPMemTest sp1 = SPMemTest(new CMemTest);
m_SPMemTest.push_back(sp1);
m_SPMemTest.push_back(sp1);
m_SPMemTest.pop_back();
m_SPMemTest.pop_back();

//이렇게 하면 삭제가 됩니다.
//다른 방법으로 사용하면 아래도 가능하죠
m_SPMemTest.push_back(SPMemTest(new CMemTest(10)));
m_SPMemTest.push_back(SPMemTest(new CMemTest));

//값을 사용할때
. 가 아니고 -> 를 사용해야 합니다.
m_SPMemTest[0]->_val = 10;

//erase와 clear만 사용하면 자동으로 메모리 삭제 됨

count = m_SPMemTest.size();
m_SPMemTest.erase(m_SPMemTest.begin());
count = m_SPMemTest.size();

m_SPMemTest.clear();

Posted by gsi
:

stl 문중에서 아마도 vector를 가장 개인적으로 선호 한다.
이론적인 내용은 우선 접어 두고.. (책을 보면 안다 ^^)

기존에 내가 했던 작업은 vector와 for문을 많이 사용했다.
이번에 accumulate, for_each를 공부 하면서 많은 부분 간소화 시키고
가독성과 범용성을 갖출수 있는 방법을 찾아 봤다.
class 의 객체를 vector에 추가 해서 작업 할때 vector의 배열 정보를 사용해서
특정 변수의 값을 다르게 변경할 작업이 많이 생긴다.

//헤더에 필요한 헤더파일을 추가한다.

#include <vector>
#include <map>
#include <algorithm>
#include <numeric>

using namespace std;

아래와 같은 클래스가 있다고 하자.

class Element {
public:
 DWORD UID;
 INT  Price;
 int  Count;
 DWORD Res_ID;

 //생성자
 Element(DWORD uid, INT price, int count, DWORD res_id, ) :
  UID(uid),
  Price(price),
  Count(count),
  Res_ID(res_id),
 {
 }

 //operator
 bool operator==(const Element& e) const {
  return (UID == e.UID) ? true : false;
 }
};

위의 코드에서 price는 가격을 뜻하고, count는 수량을 뜻한다.
Res_ID는 해당 오브젝트의 리소스 아이디라고 가정을 하자.
아래와 같은 작업을 할려고 한다.

1. Count가 음수인 요소들의 개수를 얻어 오고 싶다.
2. Count가 음수인 요소들의 Price의 총 합을 얻고 싶다.
3. Count가 음수인 요소들의 Res_ID의 목록을 얻고 싶다.

기존에 for문을 사용하게 되면 코드의 량도 늘어 나고 보기에도 좀 그렇다.
아래와 같은 accumulate 함수를 작성하고 활용하면 자연스럽게 구현이 가능하다.

//카운터가 0보다 작은 요소들의 개수
int count_minus_element_sum (int count, const Element& t1 ) {
 if(t1.Count < 0)
  count++;

 return count;
}

//카운터가 0보다 작은 요소들의 총금액
int count_minus_element_price_sum (int price, const Element& t1 )
{
 if(t1.Count < 0) {
  price += (abs(t1.Count) * t1.Price);
 }

 return price;
}

//카운터가 0보다 작은 resid를 추출
vector<DWORD>& count_minus_resid ( vector<DWORD>& v, const Element& t1 )
{
 if(t1.Count < 0) {
  v.push_back(t1.Res_ID);
 }
 return v;
}

//for_each - cout << resid << endl
void display_resid ( const DWORD& ri )
{
 cout << ri << endl;
}

//벡터 테스트
 vector< Element > m_ElementList;

//요소를 추가한다.

 m_ElementList.push_back(Element(100, 100, 1, 2000));
 m_ElementList.push_back(Element(101, 100, 2, 2001));
 m_ElementList.push_back(Element(102, 100, 3, 2002));
 m_ElementList.push_back(Element(103, 100, -1, 2003));
 m_ElementList.push_back(Element(104, 100, 0, 2004));
 m_ElementList.push_back(Element(105, 100, -2, 2005));
 m_ElementList.push_back(Element(106, 100, -3, 2006));
 m_ElementList.push_back(Element(107, 100, -1, 2007));
 m_ElementList.push_back(Element(108, 100, 2, 2008));
 m_ElementList.push_back(Element(109, 100, 3, 2009));
 m_ElementList.push_back(Element(110, 100, 6, 2010));

//음수인 요소의 개수의 총 합을 구한다.

 int count = accumulate(m_ElementList.begin(), m_ElementList.end(), 0, count_minus_element_sum);

//음수인 요소의 가격의 총 합을 구한다.
 int price = accumulate(m_ElementList.begin(), m_ElementList.end(), 0, count_minus_element_price_sum);

//음수인 요소의 Res_ID의 목록을 구한다.
 vector<DWORD> m_ResID; //목록을 담을 배열을 선언한다.
 m_ResID.clear(); //클리어
 m_ResID = accumulate(m_ElementList.begin(), m_ElementList.end(), m_ResID, count_minus_resid);

//담겨진 요소의 Res_ID를 화면에 출력해 본다.

 for_each(m_ResID.begin(), m_ResID.end(), display_resid);

위와 같이 accumulator를 잘만 사용하면 아주 다양한 효과를 볼 수 있을거 같다.
총 합을 구하거나 모든 요소의 특징을 살펴 본다거나 하는 형태의 작업에 아주 탁월하다.

for_each는 for문을 사용하는 번거로움을 조금 해소해 줄수 있다.

Posted by gsi
:

vector 라는 컨테이너 다른 경우도 포함이 되지만. 컨테이너는 지능적이기는 하지만 메모리에 대해서는 신경을 쓰지 않습니다. 즉 new로 선언한 객체의 delete가 행해 지지 않는 다는 거죠.

보통 아래의 일반적인 경우로 메모리를 처리 할수 있습니다.

//헤더 선언

#include <vector>
#include <functional> -> 아래쪽 디파인 잡을때 사용되는거
#include <algorithm> -> 아래쪽 디파인 잡을때 사용되는거
#include <iostream>

using namespace std;

//선언

 vector< int* > m_List;

//추가

 m_List.clear();

 for(int i = 0; i < 2; i++) {
  int* p = new int;
  *p = 10;
  m_List.push_back(p);
 }

//삭제

 for(vector< int* >::iterator i = m_List.begin(); i != m_List.end(); ++i)
 {
  delete (*i);
 }

// 조금 편한 삭제 방법

//디파인

class DeleteObj
{
public:
 template<typename T>
 void operator()(const T* ptr) const
 {
  delete ptr;
 }
};

//삭제

for_each(m_List.begin(), m_List.end(), DeleteObj());

위의 클래스로 템플릿을 만들어 놨기 때문에.
대부분의 객체에 삭제 함수로 적용할 수 있다.
for_each를 통해서 조금더 코드량을 줄이고 가독성을 높일수 있을거 같다.

Posted by gsi
:

vector과 string의 용법

STL 2007. 9. 6. 14:37 |

//vector

void doSomething(const int* pInts, size_t numInts) {}

int의 배열정보를 가져 올때 아래와 같이

doSomething(&v[0], v.size());

v가 빈 디렉토리일때 &v[0]가 잘못된 값을 가져 올수 있기
때문에 아래 표기가 맞습니다.

if(!v.empty()) {
   doSomething(&v[0], v.size());
}

** &v[0] == &*v.begin()

//string

void doSomething(const char *pString) {}

string로 부터 char*를 가져 올때 아래와 같이

doSomething(s.c_str());

C API : 이 함수는 최대 arraySize 만큼의 double을 가진 배열에 대한 포인터를 받아 그 배열에 데이터를 기록 합니다. 동작이 끝나고 나면 데이터가 기록된 double의 개수를 반환하는데, 이 값은 maxNumDoubles를 넘지 않습니다.

size_t fillArray(double *pArray, size_t arraySize);

크기가 maxNumDoubles인 벡터를 생성합니다.

vector<double> vd(maxNumDoubles);

fillArray를 써서 vd에 데이터를 기록하고, resize를 써서 vd의 크기를 fillArray가 반환한 수치로 맞춥니다.

vd.resize(fillArray(&vd[0], vd.size());

C API : 이 함수는 최대 arraySize 만큼의  char를 가진 배열에 대한 포인터를 받아 그 배열에 데이터를 기록합니다. 동작이 끝나고 나면 데이터가 기록된 char의 개수를 반환하는데, 이 값은 maxNumChars를 넘지 않습니다.

size_t fillString(char *pArray, size_t arraySize);

maxNumCahrs 만큼의 크기를 가진 벡터를 생성합니다.

vector<char> vc(maxNumChars);

fillString을 써서 vc에 데이터를 기록합니다.

Size_t charsWritten = fillString(&vc[0], vc.size());

vc에 s로 데이터를 복사하는데, 이때 범위 생성자를 사용합니다.

stirng s(vc.begin(), vc.begin() + charsWritten);

쓸데 없이 남은 용량 없애기 (vector)

vector가 100,000개인 데이터를 추가한 후에 10개의 데이터만을 남기가 모두 erase로 했다고 가정해 봅시다. 이때 vector는 10개의 데이터를 가지고 있지만 내부적으로는 100,000개의 데이터 공간이 존재 하게 됩니다. 즉, 불필요한 용량이 존재 하게 됩니다.

이때 swap를 사용해서 용량을 현재 크기에 맞게 설정할 수 있습니다.

vector<Contestant>(contestant).swap(contestant);

vector< Contestant>( contestant) 이 표현식은 contestant의 사본인 임시 벡터 객체를 만듭니다. 즉, vector의 복사 생성자가 contestant의 상수 참조자를 매게변수로 받아 동작하는 거죠, 단, 이 복사 생성자는 요소가 복사되는데 필요한 만큼의 메모리만을 할당하기 때문에, 이렇게 만들어지는 객체는 contestant와 달리 딱 맞는 용량이 잡혀 있게 됩니다.

그 다음 swap 문이 이어 지는데요. 이 함수에 의해서 임시 벡터 안의 데이터와 contestant안의 데이터가 완전히 싹 바뀝니다.

이렇게 되면 용량이 현재 사이즈에 맞게 수축됩니다.

swap를 거치게 되면서 데이터의 반복자, 포인터, 참조자는 그대로 유지됩니다.

Posted by gsi
:

stl vector sort

STL 2007. 9. 6. 14:36 |

#include <vector>
#include <algorithm>

using namespace std;

bool compare(type a,type b)
{
  return a>b(비교);  
}

void function()
{
  vector<type> v;
  sort(v.begin(),v.end(),compare) ;
}

Posted by gsi
:

for_each 에 대해서...(이펙티브 STL 내용 발췌.. 243 페이지)

이 알고리즘은 범위 내의 데이터를 요약할 수 있는 또 하나의 알고리즘이면서 accumulate가 가진 이상한 제한도 받지 않습니다. for_each는 범위와 그 범위 내의 요소에 대해 호출할 함수(대개 함수 객체)를 받아 들이는데, 이 알고리즘에 넘겨지는 함수는 자신이 처리할 단 하나의 요소만을 받아들이며, for_each는 자신의 수행을 마칠 때 이 함수를 반환합니다(엄밀히 말하면 그 함수의 사본(copy) 입니다.  항목 38에서 더 자세히 공부하세요). 가장 중요한 포인트는 for_each에 넘겨지는 (그리고 반환되는) 함수는 부가적 효과를 가져도 된다는 것입니다.

부가적 효과에 대한 사항을 차지하고라도, for_each는 두 가지 면에서 accumulate와 다릅니다. 우선 accumulate라는 이름 자체에서 "범위를 요약한다"는 느낌이 강하게 풍겨집니다. for_each는 "범위 내의 모든 요소에 어떤 일을 한다"라는 냄새가 나죠. 물론 이 알고리즘들의 일차적인 목적이 그것이겠지만요. 어쨌든 for_each를 써서도 범위를 요약할 수 있습니다. 하지만 accumulate처럼 확실하지 않다는 것 뿐이죠.

두번째, accumulate는 우리가 원하는 요약 결과를 바로 반환하지만, for_each는 자신이 매게 변수로 받은 함수 객체를 반환하기 때문에 이 객체에서 요약 정보를 뽑아내야 합니다. C++ 업에 용어로 말하면 for_each에 넘기는 함수자 객체에다가 요약 정보를 얻어 낼 수 있는 멤버 함수를 추가해야 한다는 의미이지요.

.. 이상..

대부분 vector의 예를 보면 간단하게 아래와 같이 서술할 겁니다.

class CTest
{
public:
  CTest() {}
  ~CTest() {}

private:
  ... 내용...
};

void Test(CTest& e) { ... 내용... }

vector<CTest> m_vTest;

//배열의 정보를 사용해서 Test() 함수를 실행할려고 할때.

vector<CTest>::iterator iter;
for(iter = m_vTest.Begin(); iter != m_vTest.End(); iter++) {
  Test((*iter));
}

//이런 형태로 구성하게 되지요.
//하지만 for_each를 구성하면 한줄로 심플하게 구성됩니다.

std::for_each(m_vTest.Begin(), m_vTest.End(), &Test);

//이렇게 한줄로 요약이 되는군요.
//여기서 조금더 확장해서  Test() 함수에 템플릿을 연동하면
//비슷한 형태의 다른 타입의 vector로 선언된 변수들을 연동할수 있습니다.

template < class T >
void Test(T& e) { ... 내용 ... }
std::for_each(m_vTest.Begin(), m_vTest.End(), &Test);

//이렇게만 구성하면 컴파일 오류가 납니다.
//아래와 같이 구성하시면 됩니다.

std::for_each(m_vTest.Begin(), m_vTest.End(), &Test<CTest>);

위의 코드는 오류가 있을지도 모릅니다. 제 나름대로 정리해본겁니다.
하지만 위의 코드가 더 다양한 방법으로 전환되기도 하더군요.
예를 들어서 CTest 클래스 내부에 Test() 함수를 넣고 그것을 for_each에 연동할 수 있더라구요.
Exceptional C++ Style 책에 보니 내용이 있더라구요.
아래와 같은 코드로 사용하면 되는듯 합니다.

std::for_each(m_vTest.Begin(), m_vTest.End(), std::mem_fun_ref( &CTest::Test));

이렇게 구성하시면 됩니다.
아 그리고 for_each는 Test가 반환되는 값이 있다면 앞쪽에 붙여서 받으면 되요.

Posted by gsi
: