0

I am a web developer and I am new to C++. I am using Qt C++. I was looking a way to generate a PBKDF2 key in Qt, but could not find a way to do that in pure C++. So looking on internet I have found this small C implementation https://github.com/ctz/fastpbkdf2. I need to use the following function

void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
                            const uint8_t *salt, size_t nsalt,
                            uint32_t iterations,
                            uint8_t *out, size_t nout)

In my C++ file, I have

QString password = "password";
QString salt = "salt";
int iterations = 30000;

I know I can directly call any C function in C++, but I am not sure about how can I call that function with those parameters from my C++ file. An explanation of data type conversions would also be appreciated.

3
  • In the answers I have noticed people listed different ways of converting QString (using toStdString() or using QByteArray). Which one would be preffered? Commented Jul 27, 2016 at 18:35
  • I would also like to have a clarification on how can I display the output of this function. Commented Jul 27, 2016 at 18:39
  • Also how can I convert uint8_t to QString? Commented Jul 28, 2016 at 20:58

3 Answers 3

1

All you need to convert QString to char (or uint8_t):

QString passoword = "password";
QByteArray ba = password.toLatin1();
const uint8_t *pw = (const uint8_t*)ba.data();

And you can use this pw in the function. The same for "salt". You can use "iterations" as it is. For "out" parameter, allocate uint8_t with any method you prefer, could be malloc.

Sign up to request clarification or add additional context in comments.

1 Comment

You might want to call toUTF8() instead, if you want to support Unicode characters outside the Latin-1 range.
1

uint8_t is a typedef for an unsigned 8-bit integer, or in other words an unsigned char.

uint32_t is a typedef for an unsigned 32-bit integer, or in other words an unsigned int.

These typedefs are defined in stdint.h. These types were introduced to have well-defined (width-wise) integer types for portability.

size_t is typically an unsigned integer type as well. So the prototype:

void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
                            const uint8_t *salt, size_t nsalt,
                            uint32_t iterations,
                            uint8_t *out, size_t nout)

is equivalent to:

void fastpbkdf2_hmac_sha256(const unsigned char* pw, unsigned int npw,
                            const unsigned char* salt, unsigned int nsalt,
                            unsigned int iterations,
                            unsigned char* out, unsigned int nout);

Others have posted how to convert QString into a unsigned character array.

1 Comment

This holds for most platforms but keep in mind that C99 types (the ones with '_t') are spec defined making them inherently more portable. 'unsigned int' and the others following that format are compiler types making it up to the compiler implementation to define them. If you are writing code for a single platform or if your code does not need to know exactly what the underlying memory is, compiler types are fine.
-1

I am not too familiar with QT so I am looking at this page as a reference for a QString. It appears to be a managed string object while the function you want to call just wants a null terminated array of uint8_ts. I think it is wrapping std::string because there is a toStdString() member function. A std::string just manages a character array which is what your function wants so you can do this: password.toStdString().c_str() to get the char *.

Most platforms will implicitly convert uint8_t and char since they are almost always straight up 1 byte of memory.

There is also an output buffer and by the calling convention it looks like you have to manage that memory. From glancing at the docs of the github you linked it will output however much memory you tell it to using nout. In this example we create a 256 byte buffer for it to output to.

QString password = "password";
QString salt = "salt";
int iterations = 30000;

const size_t nout = 256;
uint8_t * out = new uint8_t[nout];

fastpbkdf2_hmac_sha256(password.toStdString().c_str(), password.toStdString().size(),
   salt.toStdString().c_str(), salt.toStdString().size(),
   iterations,
   out, nout);

// use out

delete[] out;

2 Comments

This gives me the following error: invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}
Try reinterpret_cast<uint8_t*>() to trick the compiler since the underlying memory is identical.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.