PDA

View Full Version : Microsoft PasswordDeriveBytes implementation in Qt5/C++



Coder5546
31st July 2014, 20:43
Hi, we are trying to rewrite the function PasswordDeriveBytes from C#, but Microsoft function is not standard implementation of PKCS... it's extended...
We need this implementation to decode 3DES strings in new version of our application

C#:


String crc...
PasswordDeriveBytes passwordDeriveBytes = new PasswordDeriveBytes(crc, b);

byte[] u = passwordDeriveBytes.GetBytes(24);
byte[] iv = passwordDeriveBytes.GetBytes(8);


Qt:


QString crc..
Tools::PasswordDeriveBytes passwordDeriveBytes((byte *)crc.toUtf8().data(), b);
byte *key = passwordDeriveBytes.GetBytes(24);
byte *iv = passwordDeriveBytes.GetBytes(8);


PasswordDeriveBytes C++ Implementation found on web...


std::string Tools::PasswordDeriveBytes::convertInt(int number)
{
if (number == 0)
return "0";
std::string temp="";
std::string returnvalue="";
while (number>0)
{
temp+=number%10+48;
number/=10;
}
for (unsigned int i=0; i<temp.length(); i++)
returnvalue+=temp[temp.length()-i-1];
return returnvalue;
}

void Tools::PasswordDeriveBytes::Prepare(unsigned char *password, unsigned char *salt, int iterations)
{
if (password == NULL)
return;

Prepare(password, strlen((const char*)password), salt, strlen((const char*)salt), iterations);
}


void Tools::PasswordDeriveBytes::Prepare(unsigned char* password, int pass_len, unsigned char* salt, int salt_len, int iterations)
{
if (password == NULL)
return;

this->password = new unsigned char[pass_len];
memcpy(this->password,password,pass_len);
//memcpy((char *)this->password, (const char*)password, pass_len);
this->pass_len = pass_len;
//(unsigned char*)password.Clone();

this->salt = new unsigned char[salt_len];
//strncpy((char *)this->salt, (const char*)salt, salt_len);
memcpy(this->salt,salt,salt_len);
this->salt_len = salt_len;

this->IterationCount = iterations;
state = 0;
}

unsigned char *Tools::PasswordDeriveBytes::GetBytes(int cb)
{
if (cb < 1)
return NULL;

if (state == 0)
{
// it's now impossible to change the HashName, Salt
// and IterationCount
Reset();
state = 1;
}

unsigned char* result = new unsigned char[cb];
int cpos = 0;
// the initial hash (in reset) + at least one iteration
int iter = IterationCount-1;
if (iter < 1)
{
iter = 1;
}

// start with the PKCS5 key
if (this->output == NULL)
{
// calculate the PKCS5 key
this->output = initial;
this->output_len = SHA1_BYTES_LEN;

// generate new key material
for (int i = 0; i < iter - 1; i++)
{
SHA1((const unsigned char*)this->output,this->output_len,this->output);
this->output_len = SHA1_BYTES_LEN;
}
}

while (cpos < cb)
{
unsigned char* output2 = new unsigned char[SHA1_BYTES_LEN];
unsigned int output2_len = SHA1_BYTES_LEN;
if (hashnumber == 0)
{
SHA1((const unsigned char*)this->output,this->output_len,output2);
output2_len = SHA1_BYTES_LEN;
}
else if (hashnumber < 1000)
{
std::string n = convertInt(hashnumber);
output2 = new unsigned char[this->output_len + n.length()];
output2_len = this->output_len + n.length();
for (unsigned int j = 0; j < n.length(); j++)
output2[j] = (unsigned char)(n[j]);

memcpy(output2 + n.length(),this->output,this->output_len);
SHA1((const unsigned char*)output2,output2_len,output2);
output2_len = SHA1_BYTES_LEN;
}
else
{
return NULL;
}

int rem = this->output_len - this->position;
int l = cb - cpos;
if (l > rem)
{
l = rem;
}
memcpy(result + cpos, output2 + this->position, l);
cpos += l;
this->position += l;
while (this->position >= output2_len)
{
this->position -= output2_len;
this->hashnumber++;
}
}
return result;
}

void Tools::PasswordDeriveBytes::Reset()
{
this->state = 0;
this->position = 0;
this->hashnumber = 0;
this->initial = new unsigned char[SHA1_BYTES_LEN];
this->output = NULL;
this->output_len = 0;
if (this->salt != NULL)
{
unsigned char* rv = new unsigned char[this->pass_len + this->salt_len];
memcpy(rv,this->password, this->pass_len);
memcpy(rv + this->pass_len, this->salt, this->salt_len);
SHA1((const unsigned char*)rv,this->pass_len + this->salt_len, initial);

}
else
{
SHA1((const unsigned char*)this->password,this->pass_len,initial);
}
}


header


class PasswordDeriveBytes {
private:
unsigned char* password;
int pass_len;
unsigned char* salt;
int salt_len;
int IterationCount;
int state;
unsigned char* initial;
unsigned char* output;
unsigned int output_len;
unsigned int position;
int hashnumber;

public:
PasswordDeriveBytes(unsigned char* password, unsigned char* salt, int iterations = 100)
{
Prepare(password, salt, iterations);
}

private:
std::string convertInt(int number);
void Prepare(unsigned char* password, unsigned char* salt, int iterations);
void Prepare(unsigned char* password, int pass_len, unsigned char* salt, int salt_len, int iterations);

public:
unsigned char* GetBytes(int cb);
void Reset();
};

and Mono version (C#)



https://raw.githubusercontent.com/mono/mono/master/mcs/class/corlib/System.Security.Cryptography/PasswordDeriveBytes.cs
returned byte arrays are not identical in the two implementations
We don't know how fix this problem..

Regards and thanks for any reply

d_stranz
1st August 2014, 23:32
How is this a Qt question? You should ask this on StackOverflow or some other programming forum.