티스토리 뷰

프로그래밍/MFC

MS CryptoAPI 암호화

에어버스 2016. 6. 5. 13:35

Microsoft CryptoAPI 이용

 

<추가>
1. 프로젝트는 멀티바이트로 함.
2. 레지스트리에 저장할때는 문자열이 아닌 바이너리(이진값)로 해야 한다. (REG_BINARY)
암호화 문자열을 저장하면, 읽어와서 복호화 할때 에러난다.
3. 파일로 저장할때는 텍스트로 해보고 복호화 시 에러나면, 파일을 바이너리 모드로 저장한다.
4. 파이을 행단위로 암호화해서 복호화가 필요한 경우 복호화가 잘 안되었으므로 파일을 바이너리 모드로 해보고 그래도 안되면 데이터를 행단위로 저장하지 말고 데이터를 구분할 구분문자를 넣어 한줄로 파일에 저장해서 복호화 한 후 토큰단위로 잘라 데이터를 얻어낸다.

 

 


암호화 할 텍스트파일로 숫자, 영문, 한글 이다.

 

0. #include <wincrypt.h> 필요함.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void CCryptDlg::암호화()
{
    HCRYPTKEY hKey;
    HCRYPTPROV hCryptProv;
    HCRYPTHASH hHash;
    CHAR chPWD[10 + 1= { 0, };
    CHAR chDATA[100 + 1= { 0, };
    DWORD dwCount;
    lstrcpy(chPWD, TEXT("TEST"));
    if (CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0== FALSE)
        AfxMessageBox(TEXT("CryptAcquireContext 호출에러 발생!"));
    if (CryptCreateHash(hCryptProv, CALG_MD5, 00&hHash) == FALSE)
        AfxMessageBox(TEXT("해시 오브젝트 생성 실패!"));
    if (CryptHashData(hHash, (BYTE*)chPWD, strlen(chPWD), 0== FALSE)
        AfxMessageBox(TEXT("CryptHashData 호출에러 발생!"));
    if (CryptDeriveKey(hCryptProv, CALG_RC2, hHash, 0x00800000&hKey) == FALSE)
        AfxMessageBox(TEXT("CryptDeriveKey 호출 실패!"));
 
    CryptDestroyHash(hHash); // 해시 오브젝트 소멸
    hHash = 0;
    CString str;
    CHAR 원본파일필터[] = TEXT("Data(*.txt)|*.txt|모든파일(*.*)|*.*||");
    CFileDialog dlg(TRUE, NULLNULL, OFN_FILEMUSTEXIST | OFN_EXPLORER, 원본파일필터, this);
    CString str원본파일, str파일명, strPath;
    if (IDOK == dlg.DoModal())
    {
        str원본파일 = dlg.GetPathName();
        strPath = str원본파일;
        strPath.Replace(dlg.GetFileName(), TEXT("")); // 경로명을 얻는 함수가 있을법 한데....
    }
    else
    {
        AfxMessageBox(TEXT("원본파일 열기 실패!"));
    }
    CStdioFile f원본파일(str원본파일, CFile::modeRead);
    CStdioFile f암호화파일(strPath + TEXT("암호화파일.txt"), CFile::modeWrite | CFile::modeCreate);
    while (TRUE)
    {
        f원본파일.ReadString(str);
        if (str.IsEmpty() == TRUE)
            break;
        lstrcpy(chDATA, str); // 암호화할 문자열
        //GetDlgItem(IDC_EDIT_BASIC)->SetWindowTextA(str);
        dwCount = str.GetLength() + 1; // 문자열크기보다 +1, NULL문자까지 하는건가....
        //dwCount = strlen(chDATA); // 암호화 결과값이 이상함.
        if (CryptEncrypt(hKey, 0, TRUE, 0, (BYTE*)chDATA, &dwCount, 100== FALSE) // 암호화
            AfxMessageBox(TEXT("암호화 실패!"));
 
        str = chDATA;
        //GetDlgItem(IDC_EDIT_DECRYPT)->SetWindowTextA(str);
        f암호화파일.WriteString(str + TEXT("\n"));
    }
    if (hKey) CryptDestroyKey(hKey); // 세션키 해제
    if (hHash) CryptDestroyHash(hHash); // 해시 오브젝트 제거
    if (hCryptProv) CryptReleaseContext(hCryptProv, 0); // CSP의 핸들 해제
    f원본파일.Close();
    f암호화파일.Close();
}
cs

 

1. 파일 다이얼로그에서 암호화할 텍스트 파일을 선택하여 암호화해서 '암호화파일.txt' 로 저장한다.
44행 GetLength() + 1 해줘야 한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
BOOL CCryptDlg::복호화5()
{
    HCRYPTKEY hKey;
    HCRYPTPROV hCryptProv;
    HCRYPTHASH hHash;
    CHAR chPWD[10 + 1= { 0, };
    CHAR chDATA[100 + 1= { 0, };
    DWORD dwCount;
    lstrcpy(chPWD, TEXT("TEST"));
 
    if (CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0== FALSE)
        AfxMessageBox(TEXT("CryptAcquireContext 호출에러 발생!"));
    if (CryptCreateHash(hCryptProv, CALG_MD5, 00&hHash) == FALSE)
        AfxMessageBox(TEXT("해시 오브젝트 생성 실패!"));
    if (CryptHashData(hHash, (BYTE*)chPWD, strlen(chPWD), 0== FALSE)
        AfxMessageBox(TEXT("CryptHashData 호출에러 발생!"));
    if (CryptDeriveKey(hCryptProv, CALG_RC2, hHash, 0x00800000&hKey) == FALSE)
        AfxMessageBox(TEXT("CryptDeriveKey 호출 실패!"));
 
    CryptDestroyHash(hHash); // 해시 오브젝트 소멸
    hHash = 0;
 
    CHAR 원본파일필터[] = TEXT("Data(*.txt)|*.txt|모든파일(*.*)|*.*||");
    CFileDialog dlg(TRUE, NULLNULL, OFN_FILEMUSTEXIST | OFN_EXPLORER, 원본파일필터, this);
    CString str암호화파일, strPath;
    if (IDOK == dlg.DoModal())
    {
        str암호화파일 = dlg.GetPathName();
        strPath = str암호화파일;
        strPath.Replace(dlg.GetFileName(), TEXT("")); // 경로명을 얻는 함수가 있을법 한데....
    }
    else
    {
        AfxMessageBox(TEXT("원본파일 열기 실패!"));
    }
    CStdioFile f암호화파일(str암호화파일, CFile::modeRead);
    CStdioFile f복호화파일(strPath + TEXT("복호화파일.txt"), CFile::modeWrite | CFile::modeCreate);
    CString str;
    while (TRUE)
    {
        f암호화파일.ReadString(str);
        if (str.IsEmpty() == TRUE)
            break;
 
        lstrcpy(chDATA, str); // 복호화할 문자열
        //dwCount = str.GetLength();
        dwCount = strlen(chDATA);
        if (CryptDecrypt(hKey, 0, TRUE, 0, (BYTE*)chDATA, &dwCount) == FALSE) // 복호화
            AfxMessageBox(TEXT("CryptDecrypt 호출 실패!"));
 
        str = chDATA;
        f복호화파일.WriteString(str + TEXT("\n"));        
    }    
    if (hKey) CryptDestroyKey(hKey); // 세션키 해제
    if (hHash) CryptDestroyHash(hHash); // 해시 오브젝트 제거
    if (hCryptProv) CryptReleaseContext(hCryptProv, 0); // CSP의 핸들 해제
    f암호화파일.Close();
    f복호화파일.Close();
    //GetDlgItem(IDC_EDIT_ENCRYPT)->SetWindowTextA(str);
    return TRUE;
}
cs

 

2. 파일 다이얼로그에서 1번에서 암호화한 '암호화파일.txt' 를 선택하면 복호화해서 '복호화파일.txt' 로 저장한다.
47행 strlen(chDATA) 로 얻은 문자열 길이로 지정한다.

 

=====================

 

Crypto2010 (4).zip(VC2015 프로젝트)

 

암호화

1. 최조키셋생성

2. 암호입력

3. 암호화할 파일 선택

4. 암호화한 파일을 저장할 파일 선택

5. 암호화하기

 

복호화

1. 암호화때 사용한 암호입력

2. 암호화된 파일 선택

3. 복호화된 파일을 저장할 파일 선택

4. 복호화하기

===============================

 

블록암호인 RC2와 스트림 임호 RC4, 해시함수 MD5, SHA1을 수행

CrtptoAPI 는 MS 윈도우 OS에 포함되어 있는 암호화 LIB 집합

 

서비스 제공함수

 

1. CryptAcquireContext()

특정 CSP안에서 현재 시용자의 key container의 핸들을 가져온다.

 

2. CryptoReleaseContext()

CryptAcquireContext 함수에 의해서 가져온 핸들을 헤제한다.

 

키 생성과 교환 함수

 

1. CryptDeriverKey()

암호로 부터 키를 생성한다.

 

2. CryptDestroyKey()

키를 파기한다.

 

3. CryptDuplicateKey()

키의 상태를 포함하여 정확한 키를 복사한다.

 

4. CryptGenKey()

랜덤 키를 생성한다,

 

5. CryptGenRandom()

랜덤 데이터를 생성한다.

 

오브젝트 암호화와 복호화 함수

인증, 인증서 폐기목록, 인증 요청등을 엔코도하고 디코드하는 함수

 

데이터 암호화와 복호화 함수

암호키는 CryptEncrypt()와 CryptDecrypt()를 호출하기 위해서 먼저 암호키가 있어야 한다. 암호키는 CryptGenKey(), CryptDeriveKey(), CryptImportKey()를 사용하여 생성한다. 암호화 알고리즘은 키가 생성될때 설정된다.

CryptDecrypt()

설정된 암호키를 사용하여 암호문을 복호화 한다.

 

CryptEncrypt()

설정된 암호키를 사용하여 평문을 암호화 한다.

 

해시와 디지털 서명 함수

데이터의 해시값을 계산하며, 전자 서명을 생성하고 검증하는 함수

 

CryptCreateHash()

빈 해시 오브젝트를 생성한다

 

CryptDestroyHash()

해시 오브젝트를 파기한다.

 

CryptGetHashParam()

해시 오브젝트 파라미터를 가져온다.

 

CryptHashdata()

데이터 블록의 해시값을 계산하고 해시 오브젝트에 추가한다.

 

CryptHashSessionKey()

세션키의 해시값을 계산하고 해시 오브젝트에 추가한다.

 

CryptSetHashParam()

해시 오브젝트 파라미터를 설정한다.

 

CryptSignHash()

해시 오브젝트에 서명한다.

 

CryptVerifySignature()

해시 오브젝트의 핸들이 주어진 전자서명을 검증한다.

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31