[완료] c/c++ 에서 256bits(32bytes)짜리 key를 생성하려면 어떻게 하는게 좋을까요?
글쓴이: pogusm / 작성시간: 토, 2011/05/14 - 3:33오후
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으로 추출하면 되는걸까요?
조언부탁드립니다 굽신굽신 ㅠㅠ
Forums:
pwdbased.h
처음 붙이신 코드는 자바가 아니라 C#입니다. C#의 PasswordDeriveBytes에 해당하는 Crypto++ 클래스는 pwdbased.h 헤더에 정의되어 있습니다.
감사합니다.
PasswordDeriveBytes 랑 같은게 Crypto++에도 있던거 였군요!!
굽신굽신
[완료]
crypto++에 있는
PasswordBasedKeyDerivationFunction 사용법이 너무 복잡해서
그냥 MD5 랑 SHA256를 사용해 보기로 하였습니다. ㅠㅠ
그냥 hash 하는 것과는 차이가 있습니다.
가급적이면 패스워드기반 키 생성을 활용하시기 바라며, 그렇지 못하다면 사용자 패스워드 hash 값을 임의로 생성한 키(얘가 salt가 되겠죠.)로 암호화해서 같이 보관하는 것도 한 방법입니다.
원래 salt는 목적상 같은 패스워드에서 같은 값이 생성되면 안 됩니다. 따라서 C# 예제는 적절하지 않은 방식이라고 생각합니다.
보호하려는 평문메세지도 반복 사용될 때를 대비한다면 작성하신 예제처럼 iv를 평문으로부터 만들지 말고, 또한 C# 예제처럼 패스워드로부터 만들지 말고 독립적으로 생성하시는 것이 좋습니다.
http://msdn.microsoft.com/en-us/library/f9df14hc.aspx
Crypto++가 평가도 좋고, reference도 훌륭한데 MSDN 같은 예제나 tutorial이 없는 것은 아쉬운 점이죠.
Test code 가 상당히 풍부했던 것으로 기억하는데 test code 를 살펴보시는게 좋을 것 같습니다.
답변감사합니다.
그런데 Test code가 뭐죠?
crypto++ 예제 같은건가요??
죄송하지만 어디서 찾아야 하는지좀 알려주시면 고맙겠습니다..
간만에 Crypto++ source 분석해봤습니다.
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를 찾아보세요.
답변 감사합니다.
test.cpp 를 찾아서 보고 있는 중입니다.
소스중 오류가 있어서 빌드가 안되서 아래처럼 주석처리 하고 테스트 해보고 있습니다.
//setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1); //오류나서 주석처리함
복잡하긴 하지만, 필요한것만 뽑아서 공부하고 사용하면 될거 같네요. ㅋ
감사합니다 !!
댓글 달기