[완료] c/c++ 에서 256bits(32bytes)짜리 key를 생성하려면 어떻게 하는게 좋을까요?

pogusm의 이미지

Qt C++ 에서 Crypto++를 이용하여 AES 암호/복호화 를 연습중인데요..

key = 2a5d383d85f25b8b848620a49c2640c5412a58dcccd70fe74d15a1b58786f0ea (256bits = 32bytes)
iv = 0b6c8b9642ac265249e1c0deea74e62b (128bits = 16bytes)

이런게 필요합니다.

byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);
ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

위 코드는 자바인거 같은데, "Password" 를 근거로해서, 32byte와 16byte의 key와 iv를 세련되게 뽑아내는데요..

Qt에서 crypto++를 사용하는 저의 환경에서

#include <iostream>
 
#define CRYPTOPP_DEFAULT_NO_DLL
#include <cryptopp/dll.h>
#ifdef CRYPTOPP_WIN32_AVAILABLE
#include <windows.h>
#endif
#include <cryptopp/md5.h>
 
USING_NAMESPACE(CryptoPP)
USING_NAMESPACE(std)
const int MAX_PHRASE_LENGTH=250;
 
int main(int argc, char *argv[]) {
 
    CryptoPP::MD5 hash;
    byte digest[ CryptoPP::MD5::DIGESTSIZE ];
    std::string message = "Hello World!";
 
    hash.CalculateDigest( digest, (const byte*)message.c_str(), message.length());
 
    CryptoPP::HexEncoder encoder;
    std::string output;
    encoder.Attach( new CryptoPP::StringSink( output ) );
    encoder.Put( digest, sizeof(digest) );
    encoder.MessageEnd();
 
    std::cout << "Input string: " << message << std::endl;
    std::cout << "MD5: " << output << std::endl;
 
    return 0;
}

위처럼 하면,
"Hello World!" 문자열을 근거로하여
MD5: ED076287532E86365E841E92BFC50D8C
같이 iv로 쓸 수 있는 해쉬 값을 추출할 수 있습니다...

그런데, 동시에 "Hello World!" 문자열을 근거로하여 key로 사용할 수 있는 256bits짜리 값을 세련되게(또는 간단하게) 추출할 수 있을까요?

(key와 iv값은 비슷하지 않았으면 좋겠구요..)

그냥 iv값은 MD5로 추출하고, key값은 sha-256으로 추출하면 되는걸까요?

조언부탁드립니다 굽신굽신 ㅠㅠ

feanor의 이미지

처음 붙이신 코드는 자바가 아니라 C#입니다. C#의 PasswordDeriveBytes에 해당하는 Crypto++ 클래스는 pwdbased.h 헤더에 정의되어 있습니다.

pogusm의 이미지

PasswordDeriveBytes 랑 같은게 Crypto++에도 있던거 였군요!!

굽신굽신

pogusm의 이미지

crypto++에 있는
PasswordBasedKeyDerivationFunction 사용법이 너무 복잡해서

그냥 MD5 랑 SHA256를 사용해 보기로 하였습니다. ㅠㅠ

winner의 이미지

가급적이면 패스워드기반 키 생성을 활용하시기 바라며, 그렇지 못하다면 사용자 패스워드 hash 값을 임의로 생성한 키(얘가 salt가 되겠죠.)로 암호화해서 같이 보관하는 것도 한 방법입니다.
원래 salt는 목적상 같은 패스워드에서 같은 값이 생성되면 안 됩니다. 따라서 C# 예제는 적절하지 않은 방식이라고 생각합니다.
보호하려는 평문메세지도 반복 사용될 때를 대비한다면 작성하신 예제처럼 iv를 평문으로부터 만들지 말고, 또한 C# 예제처럼 패스워드로부터 만들지 말고 독립적으로 생성하시는 것이 좋습니다.
http://msdn.microsoft.com/en-us/library/f9df14hc.aspx

Crypto++가 평가도 좋고, reference도 훌륭한데 MSDN 같은 예제나 tutorial이 없는 것은 아쉬운 점이죠.
Test code 가 상당히 풍부했던 것으로 기억하는데 test code 를 살펴보시는게 좋을 것 같습니다.

pogusm의 이미지

그런데 Test code가 뭐죠?

crypto++ 예제 같은건가요??

죄송하지만 어디서 찾아야 하는지좀 알려주시면 고맙겠습니다..

winner의 이미지

Test code 는 말 그대로 programmer가 작성 중인 code를 test 하는 code입니다. 초중학교 산수 수학 시간에 배운 검산을 생각해보시면 됩니다.
Crypto++는 test.cpp가 test code 입니다.

오랜만에 Crypto++ source를 분석했습니다. 간만에 보니까 흥미롭네요. 예전에 분석하는 것을 포기했는데 이제는 약간 이해가 가네요. ^_^.
지금도 왜 내부적으로 auto_ptr을 써서 delete 없이 new 만으로 code 진행을 하게 했는지 이해가 안 갑니다만... Java, C#도 아닌데 말이죠.
하긴... Sink, Source 나올 때 Java에서 영향 받았다는 것을 눈치챘어야... -_-.

그건 그렇고, 원하시는 것은 test.cpp의 EncryptString, DecryptString을 분석하시면 됩니다.
DES에 SHA-1을 쓰더군요. 거기서 DES를 AES로 SHA-1을 SHA256으롷 전환하실 수 있으면 될 것 같네요.

EncryptString과, DecryptString이 DES를 활용하는 DefaultEncryptor를 분석해보면 salt는 password와 time(0), clock()을 hash해서 생성하고, key와 IV는 password와 salt를 매개변수로 다시 hash해서 생성해내네요.
이건 뭐... Crypto++가 그렇다는거고, 사실 salt와 IV의 원리를 이해하고, 일반적으로 어떻게 생성하는 예가 있는지 공부해보시는게 좋을 것 같습니다.

다시 PBKDBF(Password Based Key Derivation Function)을 보면 표준에 맞춰 추상클래스를 상속한 PKCS5_PBKDF1 나 PKCS5_PBKDF2_HMAC, PKCS12_PBKDF 중 하나를 골라서 사용하시면 됩니다. class가 가상함수와 template namespace를 위해서 만들어지고, 상태(멤버변수)는 없네요.
ValidatePBKDF와 TestPBKDF를 찾아보세요.

pogusm의 이미지

test.cpp 를 찾아서 보고 있는 중입니다.

소스중 오류가 있어서 빌드가 안되서 아래처럼 주석처리 하고 테스트 해보고 있습니다.
//setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1); //오류나서 주석처리함

복잡하긴 하지만, 필요한것만 뽑아서 공부하고 사용하면 될거 같네요. ㅋ

감사합니다 !!

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.