這是mono source code的C++快速和骯髒的翻譯執行GetBytes會(X)其中X可以是小於散列的尺寸越大。正如你可以看到我只實現了SHA1版本...
#include <iostream>
#include <string.h>
#include <openssl/sha.h>
#define SHA1_BYTES_LEN 20
using namespace std;
namespace DeriveKeys
{
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)
{
Prepare(password, salt, iterations);
}
private:
string convertInt(int number)
{
if (number == 0)
return "0";
string temp="";
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 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 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;
}
public:
unsigned char* 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)
{
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 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);
}
}
};
}
迭代計數爲2?真? RFC2898建議至少有1000 ... – caf 2010-10-05 12:57:41
雖然它與你的問題沒有任何關係,但我現在正在問自己爲什麼你要使用2的迭代計數。迭代計數的目標之一是增加所需的工作進行暴力攻擊。迭代計數爲2時,您實際上正在執行'SHA1(SHA1(message || salt))',從計算的角度來看這不是很複雜。此外,[SHA-1已損壞](http://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html)。我不知道情況,但至少使用更多的迭代。 – 2010-10-05 13:54:19