c++ - Crypto++ pbkdf2 output is different than Rfc2898DeriveBytes (C#) and crypto.pbkdf2 (JavaScript) -
so i'm trying use pbkdf2 derive key given base64 string of 256bits. able use c#'s rfc2898derivebytes , node-crypto's pbkdf2 derive same key, however, can't same c++. i'm not sure if i'm doing wrong conversions or using functions improperly, i'll let guys @ it.
c++
/* 256bit key */ string key = "y1mjycd0+o+aendy5pb58jmlms0embwgjdj2r2kw6qq="; string decodedkey; stringsource(key, true, new base64decoder(new stringsink(decodedkey))); const byte* keybyte = (const byte*) decodedkey.data(); /* generate iv */ /* autoseededrandompool prng; byte iv[aes::blocksize]; prng.generateblock(iv, sizeof(iv)); */ /* testing purposes, hardcode iv */ string iv = "5ifv54dcrq5icqbd7qhqzg=="; string decodediv; stringsource(iv, true, new base64decoder(new stringsink(decodediv))); const byte* ivbyte = (const byte *) decodediv.data(); byte derivedkey[32]; pkcs5_pbkdf2_hmac<cryptopp::sha1> pbkdf2; pbkdf2.derivekey(derivedkey, 32, 0, keybyte, 32, ivbyte, 16, 100); /* * derivedkey: 9tryxcoqltbuolqm3m4opgt6n25g+o0k090fvp/hflk= */
c#
// string key = "y1mjycd0+o+aendy5pb58jmlms0embwgjdj2r2kw6qq="; // need convert byte data string key = convert.frombase64string("y1mjycd0+o+aendy5pb58jmlms0embwgjdj2r2kw6qq="); // change above rijndaelmanaged symkey = new rijndaelmanaged(); symkey.generateiv(); /* assume hardcoded iv same above */ rfc2898derivebytes derivedkey = new rfc2898derivebytes (key, symkey.iv, 100); /* * derivedkey: dzqbpzkyupkn8pu4pyyeaw7rg8uyd6yyj3wi1mijsyc= */
js
// var key = "y1mjycd0+o+aendy5pb58jmlms0embwgjdj2r2kw6qq="; // need convert byte data var key = new buffer("y1mjycd0+o+aendy5pb58jmlms0embwgjdj2r2kw6qq=", "base64"); // changed above var iv = crypto.randombytes(16); iv = "5ifv54dcrq5icqbd7qhqzg=="; /* hardcode iv */ crypto.pbkdf2(key, iv, 100, 32, function(err, derivedkey) { } /* * derivedkey: dzqbpzkyupkn8pu4pyyeaw7rg8uyd6yyj3wi1mijsyc= */
well main questions is, doing wrong on c++'s cryptopp library not deriving same value.
solution: being dumb... realized after review original implementation on javascript , c# missed crucial step reason did not complain compiler. problem did not convert key used byte data before algorithm on c# , js implementation...
anyways, proposed solution is: not code @ 4 , make sure consistent on data conversion...
i guess tl;dr of c# , js converting 256bit key byte data ascii instead of base64 conversion.
well main questions is, doing wrong on c++'s cryptopp library not deriving same value.
well, don't think doing wrong in c++ crypto++ , pbkdf2. think other libraries setting parameters differently, or tad-bit non-standard.
i able arrive @ ietf's test vectors pbkdf2 using crypto++:
// https://www.ietf.org/rfc/rfc6070.txt // pkcs #5: password-based key derivation function 2 (pbkdf2) test vectors // // input: // p = "password" (8 octets) // s = "salt" (4 octets) // c = 1 // dklen = 20 // // output: // dk = 0c 60 c8 0f 96 1f 0e 71 // f3 a9 b5 24 af 60 12 06 // 2f e0 37 a6 (20 octets) int main(int argc, char* argv[]) { byte password[] ="password"; size_t plen = strlen((const char*)password); byte salt[] = "salt"; size_t slen = strlen((const char*)salt); int c = 1; byte derived[20]; pkcs5_pbkdf2_hmac<cryptopp::sha1> pbkdf2; pbkdf2.derivekey(derived, sizeof(derived), 0, password, plen, salt, slen, c); string result; hexencoder encoder(new stringsink(result)); encoder.put(derived, sizeof(derived)); encoder.messageend(); cout << "derived: " << result << endl; return 0; }
and run of program:
$ ./cryptopp-test.exe derived: 0c60c80f961f0e71f3a9b524af6012062fe037a6
i think first thing should verify c# , javascript implementations using same character encoding crypto++ , ietf.
if that's not it, check see if c# , javascript use purpose byte. crypto++ not, , can see implementation @ pwdbased.h.
unfortunately, little different when dial in parameters:
int main(int argc, char* argv[]) { string t1 = "y1mjycd0+o+aendy5pb58jmlms0embwgjdj2r2kw6qq="; string t2 = "5ifv54dcrq5icqbd7qhqzg=="; string pw, iv; base64decoder b1(new stringsink(pw)); b1.put((const byte*)t1.data(), t1.size()); b1.messageend(); base64decoder b2(new stringsink(iv)); b2.put((const byte*)t2.data(), t2.size()); b2.messageend(); int c = 100; byte derived[32]; cout << "pw size: " << pw.size() << endl; cout << "iv size: " << iv.size() << endl; pkcs5_pbkdf2_hmac<cryptopp::sha1> pbkdf2; pbkdf2.derivekey(derived, sizeof(derived), 0, (byte*)pw.data(), pw.size(), (byte*)iv.data(), iv.size(), c); string result; hexencoder encoder(new stringsink(result)); encoder.put(derived, sizeof(derived)); encoder.messageend(); cout << "derived: " << result << endl; return 0; }
a run results in:
$ ./cryptopp-test.exe pw size: 32 iv size: 16 derived: f6d4725c2a102d36d438baa6dcce0e3c64fa376e60fa8d0ad3dd1f569fe17e59
Comments
Post a Comment