2010-10-15 21 views
1

我需要正確加密文本(密碼),以便第三方可以解密它。他們向我提供了他們用來解密的密鑰,並告訴我他們將用OpenSSL解密它們。使用System.Security.Cryptography加密文本以匹配OpenSSL

我一直在嘗試獲取AESManaged,以及System.Security.Cryptography中的RijndaelManaged類來創建可解密但不是非常成功的東西。

OpenSSL的例子進行加密,他們提供的是:

回聲 「密碼」 | ENC -base64 -AES-256-CBC -k 「providedKey」 -p -md SHA1

所以我需要創建一個CryptoStream的是一個AES加密與256的密鑰大小,和CBC的加密模式。然後base64對結果字節數組進行編碼。這部分非常簡單。

我不確定如何創建是關鍵,我正在尋找一個正確的方向。

我注意到,在OpenSSL中由這些參數創建的所有base64解碼文本都以相同的8個字符「Salted__」開頭。所以我猜這就是Salt用來生成密鑰的。

任何人都知道如何使用私鑰和「Salted__」創建SHA1密鑰?

我知道OpenSSL.Net項目包裝的OpenSSL DLL的,但我想避免去那條路線,如果可能的話。

回答

2

感謝GregS's Point in the right direction,複製在EVP_BytesToKey()中發生的密鑰和初始向量生成非常容易。

基本上他們正在創建一個48字節的數組(密鑰是32字節數組,IV是16字節數組),並使用SHA1將私鑰和8個鹽字節散列到該緩衝區中。第一個散列只是私鑰和salt,連續的散列是與鍵和鹽字節串聯生成的最後一個散列,直到填充了48字節的數組爲止。

然後關鍵就是前32個字節,而IV是最後的16個字節。

使用System.Security.Crytpography中的AESManaged類和從此方法派生的密鑰和IV,我能夠以使用OpenSSL庫的第三方可以解密的方式加密我的密碼。

這裏是我用於導出密鑰和初始矢量的算法:

/// <summary> 
    /// Derives the key and IV. 
    /// </summary> 
    /// <param name="saltBytes">The salt bytes.</param> 
    /// <param name="privateKeyBytes">The private key bytes.</param> 
    /// <param name="iv">The iv.</param> 
    /// <returns>The Key</returns> 
    private static byte[] DeriveKeyAndIV(byte[] saltBytes, byte[] privateKeyBytes, out byte[] iv) 
    { 
     // we are creating a 16 byte initial vector and a 32 byte key 
     const int ivLength = 16; 
     iv = new byte[ivLength]; 
     const int keyLength = 32; 
     var key = new byte[keyLength]; 

     //SHA1 creates a 20 byte hash 
     const int hashLength = 20; 

     // container to store the hashed values 
     var keyContainer = new byte[keyLength + ivLength]; 

     // munge together the privateKey and salt 
     var privateKeyAndSalt = new byte[privateKeyBytes.Length + saltBytes.Length]; 
     Array.Copy(privateKeyBytes, privateKeyAndSalt, privateKeyBytes.Length); 
     Array.Copy(saltBytes, 0, privateKeyAndSalt, privateKeyBytes.Length, saltBytes.Length); 

     // use SHA1 crypto to match the -md SHA1 command line. 
     var sha1 = new SHA1CryptoServiceProvider(); 

     // hashtarget holds the successive hash's source bytes. 
     var hashtarget = new byte[hashLength + privateKeyAndSalt.Length]; 

     byte[] currentHash = null; 
     var bytesCopied = 0; 

     // do the hashing until we fill the container 
     while (bytesCopied < (ivLength + keyLength)) 
     { 
      // Hash(0) is an empty set so just concatenate private key and salt. 
      if (currentHash == null) 
      { 
       currentHash = sha1.ComputeHash(privateKeyAndSalt); 
      } 
      else 
      { 
       // successive hashes are done on Hash(prev) + private key + salt. 
       Array.Copy(currentHash, hashtarget, currentHash.Length); 
       Array.Copy(privateKeyAndSalt, 0, hashtarget, currentHash.Length, privateKeyAndSalt.Length); 
       currentHash = hashtarget; 
       currentHash = sha1.ComputeHash(currentHash); 
      } 
      var copyAmount = Math.Min(currentHash.Length, keyContainer.Length - bytesCopied); 
      Array.Copy(currentHash, 0, keyContainer, bytesCopied, copyAmount); 
      bytesCopied += copyAmount; 
     } 

     // split out bytes in the container. first 32 are key, last 16 are iv. 
     Array.Copy(keyContainer, 0, key, 0, key.Length); 
     Array.Copy(keyContainer, key.Length, iv, 0, iv.Length); 

     return key; 
    } 
1

我在相關的openssl源代碼(apps/enc.c)中探討了一些,我認爲openssl使用了一些有些專有的方法。我承認我懶得弄清楚所有的細節,但他們在那裏。它出現了ASCII字符串「Salted__」,後面跟着8個隨機鹽字節被預置在文件中。 AES密鑰 AES iv是使用名爲EVP_BytesToKey()的openssl方法從密碼和鹽得到的派生的。該算法在該手冊頁中進行了描述。在版本1.0.0a的enc.csource code中,這部分從510行開始。

希望這可以讓你開始。