1. LUCENE.NET 


Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users. The Lucene search library is based on an inverted index. Lucene.Net has three primary goals:


Maintain the existing line-by-line port from Java to C#, fully automating and commoditizing the process such that the project can easily synchronize with the Java Lucene release schedule;

Maintaining the high-performance requirements expected of a first class C# search engine library;

Maximize usability and power when used within the .NET runtime. To that end, it will present a highly idiomatic, carefully tailored API that takes advantage of many of the special features of the .NET runtime.


자바의 유명한 검색 엔진인 Lucene을 이용하여 라인 단위 포팅한 프로젝트 

언어적인 특성으로 인해 C#의 언어의 특성에 맞게 구현 됨 


http://lucenenet.apache.org/


해당 사이트에서 바이너리를 받던가 소스를 받아서 컴파일 하면 됨 



2. Lucene 인덱싱 특징


(1) 디렉토리 단위로 다큐먼트라고 불리는 인덱싱 파일들이 생성 되며, 여러 정의된 스키마를 중복으로 통합 할 수 있음 


(2) 다큐먼드는 파일시스템과 같은 디스크와 메모리에 생성 할 수 있음 

- 메모리에 생성 함으로서 속도를 개선 할 수 있다고는 하나, 경험상 체감할 정도를 아니었음 


(3) 다큐먼트의 필드 특징 

- 기본적으로 텍스트 기반으로 필드를 저장함 


- Field.Index.NO : 필드에 대해서 단순 저장용 데이터로 사용

- Field.Index.ANALYZED : 분석기에 의해 토큰화 된 데이터 

- Field.Index.NOT_ANALYZED : 검색에는 사용되나 분석기를 사용 하지 않고 사용될 데이터


- Field.Store.NO : 원본 데이터를 저장 안함 (Field.Index.ANALYZED 필드에 대해서 공간 절약 할 용도)

- Field.Store.YES : 원본 데이터를 저장 함 


(4) 기본으로 제공 되는 Analyzer(토큰화 하여 분리 시켜 주는 분석기)는 4개가 제공됨 

- WhitespaceAnalyzer : (화이트)스페이스  단위로 토큰 분리 

- SimpleAnalyzer : Letter를 구분으로 토큰 분리 

- StopAnalyzer : SimpleAnalyzer 와 같지만 Stop 단어를 제거함 

- StandardAnalyzer : 문법 기반으로 토큰 분리, 영어권 언어에 적합 



3. Lucene 한글 이슈


(1) 형태소 분석기 및 사전화 인덱싱 

- 한글을 제대로 검색 하기 위해서는 형태소 분석기 및 사전화가 되어 있어야 하나, 이 또한 적합하지 않은 경우가 있음

- 형태소 분석기 및 사전화 작업에 따른 인덱싱 속도 저하와 복잡도 및 관리 리소스가 많이 투입 될 경우가 많음

- 물론 유지보수 및 관리 잘 된다면 검색 품질을 높일 수는 있으나, 요구 사항에 따른 검색 튜닝을 해야함

 

(2) Lucene.Net.Analysis.CJK.CJKAnalyzer 사용 

- 일반적인 쇼핑몰 등의 상품명 및 정보를 검색할 경우 CJK 분석기를 이용하는 것이 유연하게 대처 가능 하다고 봄

- 인덱싱 파일이 커지고 의미상 의미 없는 단어가 검색 되긴 하지만, 기계적으로 인덱싱 속도가 빠름

- 외래어나 기타 사전화 되지 않는 단어에 대해서도 검색이 용이함 

- 3.0,3 버전 이후 부터 contrib 형태로 제공 됨 



4. 인덱싱 및 검색 전략 (Lucene.Net.Analysis.CJK.CJKAnalyzer 사용한다는 전제)


(1) 병합 전략을 위해 유니크한 id 필드를 공통으로 정의 함 (병합시 삭제 + 추가를 위해)


(2) 분석기에 의해 토큰(Field.Index.ANALYZED)화 되어지는 필드를 정하고, 이를 기반으로 보조적인 검색 필드로 일반검색

(Field.Index.NOT_ANALYZED)필드 및 그외 조회되는 데이터(Field.Index.NO)를 정의함 


(3) Field.Index.NOT_ANALYZED의 경우 분석 되지 않는 데이터이므로 대소문자 대응을 해야 함 

- http://www.gossamer-threads.com/lists/lucene/java-dev/74936


(4) 검색의 정렬의 특성상 아래의 정렬 순서로 성능이 좋음 

- http://blog.richeton.com/2009/05/12/lucene-sort-tips/ 


-  SortField.SCORE(적중율), SortField.DOC(인덱싱 문서 순서)으로 정렬, 검색 되어지게 하는 것이 성능상 좋음 

- 사용자 정의 정렬은 되도록이면 SortField.INT 를 사용하여 정렬을 할 수 있도록 인덱싱 처리  

- SortField.STRING의 경우 데이터가 많이 검색 될 경우 위의 검색 옵션 보다 월등히 성능이 좋지 않음 


(5) Lucene 검색 문법

- http://lucene.apache.org/core/3_6_1/queryparsersyntax.html


- SQL 문과 같은 문법으로 사용하기 위해 SQL 파서는 무겁다고 판단

- 아래의 정규식을 이용하여 SQL을 분리해서 Lucene 검색 문법으로 변경 처리 할 수 있음 

* 정규식 : "(?:'(?:[^']|'')*'|-?\d+(?:\.\d+)?(?:[eE]-?\d+)?|\w+|[<>=]{2}|\S)"

select(sel) [ * | field, ... ] 

from    directory 

where   field1='val' and field2='val' or ... 

order by [_score | _doc | field1 [order_expression], ...] 

group by field1, ...   


( *order_expression : [ asc | desc | doc_asc | doc_desc | score_asc | score_desc | int_asc | int_desc ] ) 

( *group result fields : group (group by value), count (group by count) )


(6) 검색 팁 

- Analyzer의 종류에 따라 토큰으로 분리가 되는 데이터가 다르므로 와일드카드 검색등을 이용할 때 고려해야 함 

  (와일드카드 검색은 성능에 영향을 미침)

- CJKAnalyzer는 중국어, 일본어, 한국어에 대해서 두 음절씩 잘라 내므로 와일드카드 검색이 의미 없을 것으로 판단


- 분야별 개수를 가져오는 Faceted Search 같은 기법은 아직 쓸모 있어 보이지 않음 (내가 잘 모를수도..)

- 그냥 직접 해쉬 맵 객체를 이용하여 구현 함 


- 토큰 필드 색인시 기본 문자열 + 공백을 제거한 문자열을 같이 포함 시켜서 넣도록 함 

- 한 글자에 대해서 검색이 용이하게 하려면 단어별로 앞글자를 공백을 넣고 같이 인덱싱 데이터에 넣으면 효과가 있을 것임

- ex) "오페라의 유령 - 25주년 기념 내한공연" 

       -> "오 유 기 내 오페라의유령25주년기념내한공연 오페라의 유령 - 25주년 기념 내한공연"  


- 사용자 검색어에 대해서 공백 단위로 AND 조건 검색 하도록 쿼리 변경 


기타 일반적인 전략 : http://wiki.apache.org/jakarta-lucene/ImproveSearchingSpeed



'Dev > .NET' 카테고리의 다른 글

SerializeToXML - C#  (0) 2009.08.10
C# Web Service -> REST  (0) 2009.08.09
Integrating WCF Services with COM+  (0) 2008.09.03
Interop 응용 프로그램 배포  (0) 2007.10.05
RCW, CCW  (0) 2007.10.04

http://msdn.microsoft.com/ko-kr/library/cc281953.aspx

서비스 계정 사용 권한

서비스는 운영 체제의 리소스 및 개체에 액세스하기 위해 계정에 로그온해야 합니다. 대부분의 서비스에서는 기본 로그온 계정을 변경할 수 없습니다. 기본 계정을 변경하면 서비스가 작동하지 않을 수 있습니다.

서비스로 로그온하는 사용 권한이 없는 계정을 선택하면 서비스 스냅인은 사용자가 관리하는 컴퓨터의 서비스로 로그온하는 데 필요한 사용자 권한을 해당 계정에 자동으로 부여합니다. 그러나 사용 권한을 부여받더라도 반드시 서비스가 시작되지는 않습니다.

서비스로 로그온하는 데 사용되는 사용자 계정은 속성 대화 상자에서 암호 사용 기간 제한 없음 확인란을 선택하고 강력한 암호를 사용하는 것이 좋습니다. 자세한 내용은 강력한 암호를 참조하십시오.

계정 잠금 정책을 사용 중이고 계정이 잠겨 있으면 서비스가 제대로 작동하지 않습니다. 자세한 내용은 계정 잠금 정책을 참조하십시오.

다음 표는 서비스 로그온 계정과 사용 방법에 대한 설명입니다.

 

로그온 계정설명

로컬 시스템 계정

로컬 시스템 계정은 도메인 컨트롤러의 디렉터리 서비스를 포함하여 시스템에 대한 완전한 액세스 권한을 갖고 있는 강력한 계정입니다. 서비스가 도메인 컨트롤러의 로컬 시스템 계정에 로그온하면 그 서비스는 전체 도메인에 대한 액세스 권한을 갖습니다. 일부 서비스는 기본적으로 로컬 시스템 계정에 로그온하도록 구성되어 있습니다. 기본 서비스 설정을 변경하지 마십시오.

로컬 서비스 계정

로컬 서비스 계정은 인증된 사용자 계정과 유사한 기본 제공되는 특별한 계정입니다. 로컬 서비스 계정은 리소스 및 개체에 대해 Users 그룹 구성원과 같은 수준의 권한을 갖습니다. 이렇게 제한된 액세스는 개별 서비스나 프로세스에 문제가 생길 경우 시스템을 보호합니다. 로컬 서비스 계정으로 실행되는 서비스는 자격 증명이 없는 Null 세션으로 네트워크 리소스에 액세스합니다.

네트워크 서비스 계정

네트워크 서비스 계정은 인증된 사용자 계정과 유사한 기본 제공되는 특별한 계정입니다. 네트워크 서비스 계정은 리소스 및 개체에 대해 Users 그룹 구성원과 같은 수준의 권한을 갖습니다. 이렇게 제한된 액세스는 개별 서비스나 프로세스에 문제가 생길 경우 시스템을 보호합니다. 네트워크 서비스 계정으로 실행되는 서비스는 컴퓨터 계정의 자격 증명을 사용하여 네트워크 리소스에 액세스합니다.

주의

  • 기본 서비스 설정을 변경하면 주요 서비스가 제대로 실행되지 않을 수 있습니다. 특히 자동으로 시작하도록 구성된 서비스의 시작 유형 및 다음 계정으로 로그온 설정을 변경할 경우에는 특별히 주의해야 합니다.
  • 대부분의 경우 서비스와 데스크톱 상호 작용 허용 설정을 변경하지 않는 것이 좋습니다. 서비스가 데스크톱과 상호 작용할 수 있게 허용되면 서비스가 데스크톱에 표시하는 모든 정보가 대화형 사용자의 데스크톱에도 표시됩니다. 악의 있는 사용자가 서비스 제어권을 가지거나 대화형 데스크톱에서 공격할 수 있습니다.

< DTC 서비스 조건 >


1. MSDTC 보안 구성 

  - 네트워크 DTC 엑세스 설정

  - 인바운드 및 아웃바운드 허용

  - 인증 필요 없음 


2. 웹서버 및 DB서버의 양방향 HOSTNAME(or 디렉토리 이름)으로 IP가 확인 가능

 

3. 양방향 RPC (135) 포트 접속 가능 


4. 양방향 동적 포트 대기 프로세스인 msdtc.exe 에 접속 가능




< MSCS 에서의 IP 설정 >


1. 클라이언트 서버에서의 DB서버의 접속은 MSCS의 DTC Group 의 IP로 접속 


2. DB 서버에서 클라이언트 접속은, MSCS의 DTC가 위치해 있는 노드의 물리적인 서버의 IP로 웹 서버로 접속 




Step by Step: 트랜잭션 오류에 대한 MSDTC 설정 확인하는 일반적인 방법

http://support.microsoft.com/kb/976963/ko



1) TCP “Three-Way Handshake” Connection Establishment Procedure



2) TCP Connection Termination Procedure



'Dev > Network' 카테고리의 다른 글

tcpdump 옵션  (0) 2013.04.08
SSL Protocol  (0) 2007.09.08
network protocol  (0) 2007.07.23

Windows Registry Editor Version 5.00
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]
@="Delete SVN Folders"
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]
@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""


레지스트리는 항상 조심.. 


'Dev > Windows' 카테고리의 다른 글

서비스 계정 사용 권한  (0) 2012.04.04
MS MTC 서비스 설정  (0) 2012.04.04
COM+ 패키지 활성화별 세션 상태 정리  (0) 2009.09.22
Redmine 세팅  (0) 2009.09.12
ATL Com Project VC++ 6 에서 VC++ 8 변환(업그레이드)  (0) 2009.03.27

- 메세지를 한번 주고 받고 세션을 종료하는 클라이언트 소켓
- boost::asio 라이브러리 사용 (boost 의 date_time, thread, system 컴파일 필요)
- boost::asio::deadline_timer 를 이용하여 timeout 기능 구현 
- 비동시 소켓으로 구현한 동기 소켓(?)



#pragma once

#include <algorithm>
using namespace std;

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

using boost::asio::ip::tcp;


struct IsEOF_Basic
{
bool operator()(const std::string &)
{
return true;
}
};



template <class Ty = IsEOF_Basic>
class ClientSocket 
{
public:
ClientSocket() : socket_(io_service_), timeout_(io_service_), nResponse_(0) {}

~ClientSocket() 
{
Close();
}

bool Connect(const string &sIP, const string &sPort) 
{
bool bResult = false;

tcp::resolver resolver(io_service_);
tcp::resolver::query query(tcp::v4(), sIP, sPort);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;

boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpoint_iterator != end)
{
socket_.close();
socket_.connect(*endpoint_iterator++, error);
}

if (!error) {
bResult = true;
}
return bResult;
}

void Send(const string &s, const int nTimeout = 5)
{
copy(s.begin(), s.end(), szBuff);

socket_.async_write_some(boost::asio::buffer(szBuff, s.length()),
boost::bind(&ClientSocket::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

timeout_.expires_from_now(boost::posix_time::seconds(nTimeout));
timeout_.async_wait(boost::bind(&ClientSocket::Timeout, this));

handle_read_wait();
}

int WaitForResponse()
{
socket_.io_service().reset();

while (socket_.io_service().run_one()) 
{
if (nResponse_) break;
}

return nResponse_;
}

void Close()
{
socket_.close();
}

std::string GetReadBuffer()
{
return sReadBuff_;
}

enum { TIMEOUT = -1, READY = 0, SUCCESS = 1 };

private:
void Timeout()
{
nResponse_ = TIMEOUT;
}

void handle_read_wait() 
{
socket_.async_read_some(boost::asio::buffer(szBuff, BUFF_SIZE),
boost::bind(&ClientSocket::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

nResponse_ = READY;
}

void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
if (error) {
Close();
return;
}

sReadBuff_.append(szBuff, szBuff + bytes_transferred);

if (IsEOF(sReadBuff_)) {
nResponse_ = SUCCESS;
}
else {
handle_read_wait();
}
}

void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
{
if (error) {
Close();
return;
}
}

private:
boost::asio::io_service io_service_;

boost::asio::deadline_timer timeout_;
tcp::socket socket_;
std::string sReadBuff_;
volatile int nResponse_;

Ty IsEOF;
enum { BUFF_SIZE = 8192};
char szBuff[BUFF_SIZE];
};

int SendPacket (
LPCSTR strIP, LPCSTR strPort, int nTimeoutSecond, LPCSTR szMessage, LPSTR szRetMessage)
{
int nResult = -2;

try {
typedef ClientSocket<> ClientSocketType;
ClientSocketType socket;

if (!socket.Connect(strIP, strPort)) {
throw -1;
}

if (nTimeoutSecond == 0) nTimeoutSecond = 5;

socket.Send(szMessage, nTimeoutSecond);
int nResponse = socket.WaitForResponse();

if (nResponse == ClientSocketType::TIMEOUT) {
throw 0;
}

if (nResponse == ClientSocketType::SUCCESS) {
std::string s = socket.GetReadBuffer();
std::copy(s.begin(), s.end(), szRetMessage);

nResult = s.size();
}
}
catch (int nErr) {
nResult = nErr;
}
catch (...) {}

return nResult;
}



'Dev > C++' 카테고리의 다른 글

[C++11] Variadic template  (0) 2014.11.02
boost 설치  (0) 2013.11.20
이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
- 이미지의 포맷 변환 및 퀄러티, 크기조정(비율) 모듈 
- Windows 환경, C++, GDI+, Component


STDMETHODIMP CMobileImage::Convert(BSTR Src, BSTR Output, BSTR ImgFormat, long Quality, long Width, long Height, VARIANT_BOOL* pSuccess)
{
*pSuccess = VARIANT_FALSE;

_bstr_t bstrSrc(Src);
_bstr_t bstrOutput(Output);
_bstr_t bstrImgFormat(ImgFormat);

ULONG_PTR gdiToken;
Gdiplus::GdiplusStartupInput gdiInput;
Gdiplus::GdiplusStartup(&gdiToken, &gdiInput, NULL);

try {
std::auto_ptr<Gdiplus::Image> pImage(Gdiplus::Image::FromFile((LPCWSTR)bstrSrc));
if (!pImage.get()) {
throw -1;
}

CLSID m_pngClsid;
if (GetEncoderClsid((LPCWSTR)ImgFormat, &m_pngClsid) == -1) {
throw -1;
}
else {
Gdiplus::EncoderParameters params;
params.Count = 1;
params.Parameter[0].Guid = Gdiplus::EncoderQuality;
params.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong;
params.Parameter[0].NumberOfValues = 1;

long Value = Quality;
params.Parameter[0].Value = &Value;

if (Width > 0 && Height > 0) {
std::auto_ptr<Gdiplus::Bitmap> pResize(new Gdiplus::Bitmap(Width, Height, PixelFormat24bppRGB));
std::auto_ptr<Gdiplus::Graphics> pGrap(Gdiplus::Graphics::FromImage(pResize.get()));
pGrap->DrawImage(pImage.get(), 0, 0, Width, Height);

pResize->Save((LPCWSTR)bstrOutput, &m_pngClsid, &params);
}
else {
pImage->Save((LPCWSTR)bstrOutput, &m_pngClsid, &params);
}
}

*pSuccess = VARIANT_TRUE;
}
catch (...) { }

Gdiplus::GdiplusShutdown(gdiToken);

if (m_spObjectContext) { m_spObjectContext->SetComplete(); }

return S_OK;
}


int CMobileImage::GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
using namespace Gdiplus;

UINT  num = 0;          // number of image encoders
UINT  size = 0;         // size of the image encoder array in bytes

ImageCodecInfo* pImageCodecInfo = NULL;

GetImageEncodersSize(&num, &size);
if(size == 0)
return -1;  // Failure

pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1;  // Failure

GetImageEncoders(num, size, pImageCodecInfo);

for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;  // Success
}    
}

free(pImageCodecInfo);
return -1;  // Failure
}

'Dev > C++' 카테고리의 다른 글

boost 설치  (0) 2013.11.20
boost::asio 클라이언트 소켓 (timeout 기능)  (0) 2010.10.14
C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
C++0x 지원 컴파일러 목록  (0) 2009.05.20

2021년 신규 작성 

CryotoPP Example - cdeclog

 

CryotoPP Example

CryptoPP https://www.cryptopp.com/ Crypto++ 사용하기, 예제 암호화 지식 (개발자)

cdecl.github.io

 

--

C++ 용 암호화 라이브러리
 
Crypto++ 컴파일 
 
우선 해당 사이트에서 라이브러리를 다운 받은 후 원하는 컴파일러로 컴파일을 하여 dll 이나 lib 파일을 생성한다.
VC++ 2008 버전의 경우 프로젝트 파일이 따로 있지는 않고 VC++2005 버전을 업그레이드 후 컴파일 하면 됨
 
컴파일을 하면 cryptopp560\Win32 디렉토리에 각각 파일이 생성되고, dll 의 경우는 cryptopp560\Win32\DLL_Output 폴더에, static library 의 경우는 cryptopp560\Win32\Output 폴더에 각각의 모듈이 생성 된다. 
 
내가 테스트 할때는 dll 의 버전의 경우 이상하게 링크에러가 발생을 하여,
static library 를 사용하여 테스트를 하고 어플리케이션의 경우도 static library 로 컴파일을 해야 문제가 없었다.
 
블록 알고리즘 고려사항 
알고리즘 종류, 블록 알고리즘 운영 모드, 패딩종류, 인코딩 (텍스트 암호화의 경우)
 
알고리즘 SEED, AES, DES, 3-DES 설명 
 
 
DES
가장 오래되고, 세계적으로 가장 널리 사용되는 고전적 암호화 알고리즘이다. 파일이나 패킷을 암호화할 때 많이 사용된다. 하지만, 64비트 입력 블록과 56비트 짧은 비밀키를 사용하기 때문에, 더 이상 안전하지 않다고 간주하고 있다. 그러나, 국가 기밀을 다룰 정도로 극히 중요한 보안이 아니라면, 여전히 가장 널리 사용되는 알고리즘이다.
 
3-DES
DES를 3번 반복해서 암호화한다. 보안성이 향상되고, 그 만큼 성능은 떨어진다.
 
AES
미국 NIST에서 공모해서 표준화한 새로운 알고리즘이다. 128비트 입력 블록을 도입함으로써, 보안성을 향상했으며, 최근에 세계적으로 널리 사용되는 알고리즘이다.
 
SEED
KISA 주관으로 ETRI와 함께 국내에서 만들어진 알고리즘이다. 역시, 128비트 입력 블록을 사용하고 있고, 국제 표준에 부합하는 알고리즘이다.
 
 
 
 
블록 알고리즘 운영 모드 
 
ECB(Electronic codebook) : 평문을 일정 크기의 블록으로 나누어서 처리, 각 블록은 동일한 키로 암호
CBC(Cipher-block chaining) : 평문 블록과 바로 직전의 암호블록을 XOR한 것. 첫번째 암호 블록을 위해 초기 벡터 IV 값 사용
 
기타..
PCBC(Propagating cipher-block chaining)
CFB(Cipher feedback)
OFB(Output feedback)
CTR(Counter)
 
 
패딩(Padding) 종류
 
enum BlockPaddingScheme 
{NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
 
NO_PADDING : 패딩 없음
ZEROS_PADDING : NULL(0) 으로 패딩 
PKCS_PADDING : 패딩되는 바이트의 수의 같은 값으로 모두 패딩
ONE_AND_ZEROS_PADDING :  ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding
DEFAULT_PADDING : DEFAULT_PADDING means PKCS_PADDING 
  if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode), otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes)
 
 
예제, 필요한 헤더파일 (SEED, AES, DES 사용시..)
#include <iostream>
using namespace std;

//#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1   

// Crypto++ Includes
#include "cryptlib.h"
#include "Base64.h"
#include "aes.h"        
#include "seed.h"
#include "des.h"
#include "modes.h"      
#include "filters.h"    

#pragma comment(lib, "cryptlib")  

template <class TyMode>
std::string Encrypt(TyMode &Encryptor, const std::string &PlainText)
{
	std::string EncodedText;

	try {
		CryptoPP::StringSource(PlainText, true,
			new CryptoPP::StreamTransformationFilter(Encryptor,
				new CryptoPP::Base64Encoder(
					new CryptoPP::StringSink(EncodedText), false
					), CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
				)
			);
	}
	catch (...) {}

	return EncodedText;
}

template <class TyMode>
std::string Decrypt(TyMode &Decryptor, const std::string &EncodedText)
{
	std::string RecoveredText;

	try {
		CryptoPP::StringSource(EncodedText, true,
			new CryptoPP::Base64Decoder(
				new CryptoPP::StreamTransformationFilter(Decryptor,
					new CryptoPP::StringSink(RecoveredText),
					CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
					)
				)
			);
	}
	catch (...) {}

	return RecoveredText;
}

template <class Ty>
std::string CBC_Encrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string CBC_Decrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Decrypt(Decryptor, PlainText);
}

template <class Ty>
std::string ECB_Encrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string ECB_Decrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Decrypt(Decryptor, PlainText);
}


template <class CryptoType>
void Test()
{
	using namespace std;

	const std::string sText = "Plain Text";
	std::string sEnc, sDec;

	byte KEY[CryptoType::DEFAULT_KEYLENGTH] = { 0, };
	byte IV[CryptoType::BLOCKSIZE] = { 0x01, };

	// CBC 모드
	sEnc = CBC_Encrypt<CryptoType>(KEY, IV, sText);
	sDec = CBC_Decrypt<CryptoType>(KEY, IV, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "CBC_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;


	// ECB 모드
	sEnc = ECB_Encrypt<CryptoType>(KEY, sText);
	sDec = ECB_Decrypt<CryptoType>(KEY, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "ECB_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;
	cout << endl;
}


int main()
{
	using namespace std;

	// SEED 
	Test<CryptoPP::SEED>();

	// AES 
	Test<CryptoPP::AES>();

	// DES 
	Test<CryptoPP::DES>();

	return 0;
}
  
 

 


 패키지 활성화   JIT 활성화  멤버변수 상태 유지  전역변수 상태
 1. 서버 응용 프로그램  활성  유지 않함  유지 (활성화 개체 단위)
 2. 서버 응용 프로그램  비 활성  유지  유지 (활성화 개체 단위)
 3. 라이브러리 응용 프로그램  활성  유지 않함  유지 (세션 단위)
 4. 라이브러리 응용 프로그램  비 활성  유지  유지 (세션 단위)

* JIT 활성화가 있는경우 Method 단위로 m_spObjectContext->SetComplete() 를 호출 하여 테스트
* 풀링의 세팅의 경우 위의 결과와 틀리게 멤버변수의 상태가 달라 질 수 있음 
* CreateObject 이후 Nothing 까지의 상태 


내용 
- JIT 활성화인 경우 Method 단위로 클래스의 생성자 및 소멸자 호출 
- 풀링 설정의 경우 패키지가 시작할때 풀링된 구성요소 만큼 생성자를 호출하여 인스턴스 생성해 놓음 
- 라이브러리 응용 프로그램의 경우 인프로세스로 실행 되므로 전역변수값은 세션별로만 유지함
- regsvr32 로 등록되어 있는 컴포넌트랑 같은 효과를 내기 위해서는 "라이브러리 응용 프로그램, JIT 비활성화"로 운영

결론
내가 만들지 않은 컴포넌트의 경우 내부적으로 개체의 상태값 유지를 위해서,
멤버변수를 사용했는지, 지역 변수를 사용했는지 알 수 없기 때문에 regsvr32 로 등록하여 사용 하는것으로 권장

허나 COM+에 등록하여 사용 하려면 위의 내용 참고



'Dev > Windows' 카테고리의 다른 글

MS MTC 서비스 설정  (0) 2012.04.04
.svn 폴더 삭제  (0) 2011.03.25
Redmine 세팅  (0) 2009.09.12
ATL Com Project VC++ 6 에서 VC++ 8 변환(업그레이드)  (0) 2009.03.27
유니코드(UNICODE), C++  (0) 2008.10.16
BitNami Redmine Stack 받기: http://bitnami.org/stack/redmine


한글을 문제 없이 사용위해 DB를 UTF-8 로 설정 하기 위한 작업 + 기타 등등..

1. MySql 설정 변경 
-> \BitNami Redmine Stack\mysql\my.ini 

[client] 
default-character-set=utf8

[mysqld] 
character-set-client-handshake = FALSE 
init_connect=SET collation_connection = utf8_general_ci 
init_connect=SET NAMES utf8 
default-character-set=utf8 
character-set-server=utf8 
collation-server=utf8_general_ci

[mysql] 
default-character-set=utf8


2. MySql 설정 확인
-> \BitNami Redmine Stack\mysql\bin\mysql -uroot -p 

mysql> show variables like 'c%';
mysql> status;


3. 기존 bitnami_redmine DB, UTF-8로 다시 만들기 

mysql> drop database bitnami_redmine ;
mysql> CREATE DATABASE bitnami_redmine DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


4. 어플리케이션 DB 접속 encoding 수정 
-> \BitNami Redmine Stack\apps\redmine\config\database.yml

production:
  adapter: mysql
  database: redmine_production
  host: localhost
  username: bitnami
  password: bitnami 
  port: 3306
  encoding: utf8


5. 생성된 bitnami_redmine DB 설정 초기화 작업 

// 환경변수 세팅 
\BitNami Redmine Stack\scripts>setenv.bat
// DB Migration
\BitNami Redmine Stack\apps\redmine>rake db:migrate RAILS_ENV="production"


6. SMTP 설정 : 로컬 SMTP 서버 이용 
email.yml 수정 (기존 파일이 없을 경우 email.yml.example 를 복사후 rename)
->\BitNami Redmine Stack\apps\redmine\config\email.yml

production:
  delivery_method: :smtp
  smtp_settings:
    address: localhost
    port: 25
    domain:   
    authentication:
    user_name: 
    password: 
  

7. "일감" -> "이슈" 로 Replace (일감이란 단어의 어감이 좋지 않아서;;)
-> \BitNami Redmine Stack\apps\redmine\lang\ko.yml


출처 : 

+ Recent posts