2010-10-04 156 views
1

PasswordDeriveBytes我有如下C#代碼:
等效於OpenSSL的


     private static string password = "Password"; 
     private static string salt = "SALT"; 
     private static string hashAlgorithm = "SHA1"; 
     private static int iterations = 2; 

     var saltValueBytes = Encoding.UTF8.GetBytes(salt); 
     var passwordKey = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, iterations) 
... 

我需要實現在Mac上一樣,我才知道,Opnessl實現相關方法(即libcrypto)。

上面代碼中Opnessl的等效方法是什麼?

+1

迭代計數爲2?真? RFC2898建議至少有1000 ... – caf 2010-10-05 12:57:41

+0

雖然它與你的問題沒有任何關係,但我現在正在問自己爲什麼你要使用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

回答

3

這顯示瞭如何使用OpenSSL實現PBKDF1,根據文檔是PasswordDeriveBytes使用的算法。

#include <string.h> 
#include <stdlib.h> 
#include <openssl/sha.h> 

void pbkdf1(const char *password, const char *salt, long iter, unsigned char dk[SHA_DIGEST_LENGTH]) 
{ 
    size_t pwlen = strlen(password); 
    size_t dlen = pwlen + 8; 
    unsigned char *buf; 

    if (dlen > SHA_DIGEST_LENGTH) 
     buf = malloc(dlen); 
    else 
     buf = malloc(SHA_DIGEST_LENGTH); 

    memcpy(buf, password, pwlen); 
    strncpy((char *)buf + pwlen, salt, 8); 

    while (iter-- > 0) 
    { 
     SHA1(buf, dlen, buf); 
     dlen = SHA_DIGEST_LENGTH; 
    } 

    memcpy(dk, buf, SHA_DIGEST_LENGTH); 
    free(buf); 
} 
+0

謝謝caf。但它不符合PasswordDeriveBytes。由PasswordDeriveBytes生成的Base64編碼字符串是vYJcVqBV40q+9wT/X0/MAa2nr7Epvz1u4p6LdGYNwC4=。您給出的方法生成字符串809DD7DDGZ+3wzWqnqP9kAIVa5j/fwAAAAAEAAEAAAA= Raviprakash 2010-10-06 05:07:50

+0

@Devara Gudda:帶有SHA1的PBKDF1作爲散列不能生成超過20個字節的輸出,但是您給出的那些base64字符串是32字節的數據,所以* something *是向上。您必須準確找出PasswordDeriveBytes與真正的PBKDF1的不同之處。 – caf 2010-10-06 09:09:04

1

OpenSSL實現PBKDF2,.NET公開爲Rfc2898DeriveBytesPasswordDeriveBytes使用(根據the .NET 4 docs)「PBKDF1算法的擴展」。 PBKDF1沒有被OpenSSL公開(並且誰知道問題的'擴展'可能是什麼)。

如果可能,使用PBKDF2(aka Rfc2898DeriveBytes)將爲您節省很多問題。

+0

我無法更改.NET代碼,我必須使用OpenSSL實現相同的加密。 – Raviprakash 2010-10-05 04:38:33

0

這是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); 
    } 
    } 
}; 
}