5

I am using OpenSSl in DevC. I was having a problem programming the PBKDF. A person suggested that I use the default function called PKCS5_PBKDF2_HMAC . I have visited many links online but cannot get this to work.My code from the main() is as follows

unsigned char pass[1024];      // passphrase read from stdin
unsigned char salt[1024];      // salt 
int iter=1000, keylen=128;     // iteration
unsigned char result[1024];    // result
PKCS5_PBKDF2_HMAC (pass, strlen(pass), salt, strlen(salt), iter, EVP_MD(), keylen , result);

I have just two compilation errors that are as follows:

  • too few arguments to function 'PKCS5_PBKDF2_HMAC'
  • expected expression before 'EVP_MD'

To troubleshoot I checked the header file and also verified that I am supplying the correct parameter and in the correct order but I have no solution and I am just baffled.

jww
  • 97,681
  • 90
  • 411
  • 885
  • 1
    Note that you should not use a salt of that size. You should only use `strlen` on character arrays that represent null terminated strings, not arrays. – Maarten Bodewes Feb 13 '16 at 17:28
  • 1
    @Professor: *"I have just two compilation errors that are as follows..."* - please copy and paste the *exact* error messages you are receiving, including the little tick marks the compiler uses to indicate the problem expressions. Your `pass` and `salt` are unintialized garbage. `keylen` should be bytes, not bits. – jww Feb 14 '16 at 00:57

2 Answers2

11

You have a few major mistakes, but the idea is solid.

  • EVP_* needs to be a particular function.

  • keylen=128 is a mistake for password hashing, which your example appears to be. Don't forget - never ask for more (binary) bytes of output than the native hash function supports, because then you're doing your iteration count * (keylen / native hash size) times, and the attacker only needs to do iteration count * 1 times.

    • 20 for SHA-1

    • 28 for SHA-224

    • 32 for SHA-256

    • 48 for SHA-384

    • 64 for SHA-512

  • result[1024] is far too large. result[keylen] is correct.

  • Watch out for buffer overflow if someone puts more than 1024 bytes in.

I have OpenSSL PBKDF2 example code in my Github repository (as well as PolarSSL and a variety of others), but the key example would be (using PBKDF2-HMAC-SHA-512, as the best of the options):

void PBKDF2_HMAC_SHA_512(const char* pass, const unsigned char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult, uint8_t* binResult)
{
    unsigned int i;
    unsigned char digest[outputBytes];
    PKCS5_PBKDF2_HMAC(pass, strlen(pass), salt, strlen(salt), iterations, EVP_sha512(), outputBytes, digest);
    for (i = 0; i < sizeof(digest); i++)
      {
        sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
        binResult[i] = digest[i];
      };

}

And it would be called by:

 // 2*outputBytes+1 is 2 hex bytes per binary byte, and one character at the end for the string-terminating \0
  char hexResult[2*outputBytes+1];
  memset(hexResult,0,sizeof(hexResult));
  uint8_t binResult[outputBytes];
  memset(hexResult,0,sizeof(binResult));

PBKDF2_HMAC_SHA_512(pass, salt, iterations, outputBytes, hexResult, binResult);

Try to use SHA-384 or SHA-512 as the base hash function; they include 64-bit operations that reduce most GPU based attackers margin of advantage over you.

Use a large (hundreds of thousands to tens of thousands) number of iterations. Even larger for SHA-1.

I also have a large list of test vectors in my Github repository - you can use them to verify that your code is returning the results it should.

Anti-weakpasswords
  • 2,604
  • 20
  • 25
0

The following unit compiled and gave the result required by RFC6070.

#include <openssl/evp.h>
#include <iostream>

enum { KEYLENGTH = 16 };

int main(int argc, char *argv[])
{
  char pass[]="pass\0word";
  unsigned char salt[] = "sa\0lt";
  int iter=4096;
  unsigned char result[KEYLENGTH];
  int success = PKCS5_PBKDF2_HMAC (pass, sizeof(pass) -1, salt, sizeof(salt)-1, iter, EVP_sha1(), KEYLENGTH , result);
  // catch success == 0      
  // using Qt for quick outputting
  QByteArray resultBytes((char*)result,KEYLENGTH);
  QByteArray resultHex = resultBytes.toHex();
  std::cout << resultHex.data();
  // will output 56fa6aa75548099dcc37d7f03425e0c3
  return 0;
}
adlag
  • 1,016
  • 9
  • 19
  • Thanks for replying. I encountered a number of errors which were due to the absence of the zlib library. Installed this and ended up with some new errors like: undefined reference to `CreateDCA@16' – The Nutty Professor Feb 14 '16 at 14:57