Reference-Request
這是正確的 PBKDF2 密鑰派生函式算法嗎?
我最近開始實現 PBKDF2 算法,由於我是加密新手,我想問一下我的實現是否好。
我查閱了一些文件,並嘗試遵循其中的許多文件,但現在我真的很困惑。
我遵循的文件:
https://en.wikipedia.org/wiki/PBKDF2
https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
crackstation(.)net/hashing-security.htm#properhashing // (抱歉,我不能發布超過 2 個連結。)還有更多我沒有連結的連結。
這是我的 C/C++ 程式碼:
typedef unsigned long UL; volatile class KDF2 { #define hLenSz 32 // Block size of sha256 in bytes public: KDF2() { } //Password-Based Key Derivation Function 2 std::string PBKDF2(string Password, string Salt, int c, int dkLen) { //Restrict max 128 bytes of Derivated Key if(dkLen > 128) { dkLen = 128; } const int BlockSize = hLenSz / sizeof(UL); // 8 bytes UL T[32] = {}; // Holds DK in 4 byte chunks UL L[BlockSize] = {}; UL H[BlockSize] = {}; string hash = ""; string innerSalt = Salt + (char)dkLen; int l = ceil((float)dkLen / (float)hLenSz); // Compute the number of passes needed to get the desired DK length for(int i = 0; i < l; i++) { memset(L, 0, sizeof(L)); //Iterate c times for(int j = 0; j < c; j++) { hash = HMAC(innerSalt, Password); innerSalt = hash; HexToLong(hash, H, BlockSize); //XOR function for(int p = 0; p < BlockSize; p++) { L[p] = L[p] ^ H[p]; } } for(int x = 0; x < BlockSize; x++) { T[BlockSize * i + x] = L[x]; } } std::string output = ""; for(int i = 0; i < dkLen / sizeof(UL); i++) // dkLen / 4 - unsigned long has 4 bytes { // hexify takes sizeof(T) and converts it to hex bytes output += hexify<UL>(T[i]); } return output; } private: //Hash-based message authentication code std::string HMAC(string Salt, string Password) { char c; string s; UL Key[16] = {0}; UL X[16] = {0}; UL Y[16] = {0}; UL ipad = 0x36363636; // 0x36 = 54 = '6' UL opad = 0x5c5c5c5c; // 0x5c = 92 = '\' int k; s = ""; //Process string key into sub-key //Hash key in case it is less than 64 bytes if(Password.length() > 64) { string tmp = sha256(Password); HexToLong(tmp, Key, 5); } else { for(int i = 0; i < 16; i++) { for(int j = 0; j < 4; j++) { if(4 * i + j <= Password.length()) { k = Password[4 * i + j]; } else { k = 0; } if(k < 0) { k = k + 256; } Key[i] += +k*pow(256, (double)3 - j); } } } for(int i = 0; i < 16; i++) { X[i] = Key[i] ^ ipad; Y[i] = Key[i] ^ opad; } //Turn X-Array into a String for(int i = 0; i < 16; i++) { for(int j = 0; j < 4; j++) { c = ((X[i] >> 8 * (3 - j)) % 256); s += c; } } //Append text to string s += Salt; string tmp = sha256(s); HexToLong(tmp, Key, 5); s = ""; //Convert Y array to a string for(int i = 0; i < 16; i++) { for(int j = 0; j < 4; j++) { c = ((Y[i] >> 8 * (3 - j)) % 256); s += c; } } for(int i = 0; i < 5; i++) { for(int j = 0; j < 4; j++) { c = ((Key[i] >> 8 * (3 - j)) % 256); s += c; } } //Hash final aggregated string return sha256(s); } UL f(UL B, UL C, UL D, int t) { if(t < 20) { return ((B & C) ^ ((~B) & D)); } if((t > 19) & (t < 40)) { return (B ^ C ^ D); } if((t > 39) & (t < 60)) { return ((B & C) ^ (B & D) ^ (C & D)); } if(t > 59) { return (B ^ C ^ D); } } template< typename T > std::string hexify(T i) { std::stringbuf buf; std::ostream os(&buf); os << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex << i; return buf.str().c_str(); } void HexToLong(string input, unsigned long* output, int outSize) { char hx[8] = {}; for(int i = 0; i < outSize; i++) { for(int j = 0; j < 8; j++) { hx[j] = input[j + (8 * i)]; } output[i] = strtoul(hx, nullptr, 16); } } };
該類是不穩定的,因為有時我遇到了優化問題。我還沒有弄清楚問題可能出在哪裡。
所以說清楚,我最後的問題是:
- 這是一個合適的 PBKDF2 算法嗎?
- PBKDF2 是否應該包含 HMAC 函式或只是用給定的迭代次數一遍又一遍地迭代一些雜湊?
- 如何增強系統?
似乎沒有 PBKDF2-HMAC-SHA256 的官方測試向量。StackOverflow 使用者發布了一些其他人已經驗證的測試向量。這是您也應該執行的 HMAC-SHA2的測試向量。
也就是說,如果你“實現了一些其他的東西,會使最終輸出不同”,那麼你就沒有 PBKDF2。PBKDF2 是一個標準。如果偏離標準,則沒有 PBKDF2。除非您真的知道自己在做什麼並且有充分的理由這樣做,否則您永遠不應該偏離標準。
如何增強系統?
取決於你的目標是什麼。如果您想嘗試增強 PBKDF2 的安全性,您首先必須定義您認為 PBKDF2 不足以滿足您的需求的地方。