PBKDF2 implementation in OpenSSL
Asked Answered
D

2

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.

Dunnage answered 13/2, 2016 at 15:1 Comment(2)
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.Botheration
@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.Dichotomy
C
12

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.

Compotation answered 15/2, 2016 at 5:31 Comment(0)
L
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;
}
Loudhailer answered 14/2, 2016 at 10:56 Comment(1)
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'Dunnage

© 2022 - 2025 — McMap. All rights reserved.