2011. 12. 14. 18:09

VC9.0에서 crypto++ library를 이용하여 SHA256(sha2) 구하기

(보다 간단한 버전으로, http://greenfishblog.tistory.com/129 가 있으니 참고 바랍니다.)

바이너리의 무결성 체크를 위해 hash를 사용하는데,
주로 SHA를 이용합니다.
최근에 현업에서 SHA256(혹은 SHA2)의 요구조건이 있는데,
불행하게도 Win32 API로는 SHA2를 구하는데 제약사항이 있습니다.
(ALG_ID(링크)를 보면, SHA256은 대체적으로 Vista 이상의 OS에서 지원됩니다.)

그래서, SHA256을 직접 구현해야 되는데,
문제는 "버그"입니다. 즉, Hash라는 중요한 모듈에 버그가 있다면, 큰일날 노릇이죠.
그래서 안정성있는 코드를 사용하는것은 무었보다도 중요합니다.

보통 openssl에도 sha256이 있는데,
openssl은,

  • 빌드가 쉽지않다. (즉, SHA256 부분만 가져오기가 힘들다)
  • 라이선스가 좀 까다롭다

와 같은 제약이 있습니다.

그래서 알아본 결과 crypto++ 이라는 라이브러리가 있던데,
FIPS-2 Level 1 통과도 되었으니, 나름 안정성있는 코드라 봅니다.
물론 Public Domain이라 사용 제한도 없구요.

문제는, crypto++를 가져오고 빌드하는 문제입니다.
물론, crypto++도 VC 빌드가 있으나,
전체가 아니라, sha256 부분만 가져오도록 하는것이 본 블로그 포스트의 목적입니다.

빌드를 완성시킨, sha256을 공유하니 확인해 보시기 바랍니다.
우선, x64 platform까지 추가된 프로젝트를 가정하고,
상위 경로에 Common에 CryptoppSHA256.cpp/.h가 Main Body이며,
상위 경로에 OpenSrc\cryptopp561에 crypto++ 코드가 들어있다고 가정합니다.

개발의 귀차니즘으로 CryptoppSHA256.cpp는 CString을 사용하는데,
ATL 정도만 Link하면 빌드가 됩니다.
물론, ATL 사용이 어렵다면, CString 대신 TCHAR buffer가 들어가도록 구현하세요.
그러면 순수 C++로 구현이 될 것입니다.

우선, 아래와 같이 crypto++의 .cpp 코드를 가져오기 합니다.
물론, SHA256 실행을 위한 최소한의 코드입니다.



위와 같은 cpp 목록의 속성을 들어가 precompile header를 Off 시킵니다.
이런 작업은 되도록 All Configuration & All Platfoms로 하시기 바랍니다.


그리고, 아래의 2개의 cpp를 추가합니다. 물론, precompile header도 Off 시킵니다.


그리고 위 2개의 파일을 X64에서만 빌드되도록 합니다.
즉, 위 2개의 파일의 속성에서, All Configurations & Win32 조합으로, Excluded From Build를 Yes합니다.


그리고, x64dll.asm을 추가합니다.

위와 같이 창이 뜨면 Cancel 하시기 바랍니다.

x64dll.asm도 아까전의 2개 파일처럼 x64에서만 빌드되도록 합니다.

그리고, 마지막으로, 프로젝트의 .vcproj에서 x64dll.asm이 선언된 부분을 아래의 내용으로 overwrite합니다.
(tab이 깨지는데, 정확한 내용은 sha256.zip::CrpytoSHA256\CrpytoSHA256.vcproj를 참고하세요)

    <File
     RelativePath="..\OpenSrc\cryptopp561\x64dll.asm"
     >
     <FileConfiguration
      Name="Debug|Win32"
      ExcludedFromBuild="true"
      >
      <Tool
       Name="VCCustomBuildTool"
      />
     </FileConfiguration>
     <FileConfiguration
      Name="Debug|x64"
      >
      <Tool
       Name="VCCustomBuildTool"
       CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
       Outputs="$(IntDir)\x64dll.obj"
      />
     </FileConfiguration>
     <FileConfiguration
      Name="Release|Win32"
      ExcludedFromBuild="true"
      >
      <Tool
       Name="VCCustomBuildTool"
      />
     </FileConfiguration>
     <FileConfiguration
      Name="Release|x64"
      >
      <Tool
       Name="VCCustomBuildTool"
       CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
       Outputs="$(IntDir)\x64dll.obj"
      />
     </FileConfiguration>
    </File>

이렇게 하면, Win32와 x64모두 빌드가 됩니다.

첨부된 sample은 "abc"에 대한 sha256 값을 검증하는 내용입니다.
코드는,
#include "CryptoppSHA256.h"
...
CString strSHA256;
...
CCryptoppSHA256::GetSHA256AndVerify((LPBYTE)"abc", 3, strSHA256);
와 같이 하면 됩니다.
리턴값은 Win32 ErrorCode입니다.

CString을 사용하기 때문에, ATL이나 MFC를 사용합니다.
물론, TCHAR 버퍼를 사용하도록 코드 수정 하면 해당 의존성은 제거될 것입니다.

cryptopp561의 testvectors 경로에 sha.txt가 있습니다.
그곳의 내용으로 verify할 수 있습니다.
물론, Win32 / x64 모두 제대로 동작함을 알 수 있습니다.