2012-08-29 25 views
1

一直試圖冒險出去學習一些C#和PowerShell,給自己一些小項目去嘗試和學習。最近我一直試圖將一些代碼從PowerShell轉換爲C#,我相信我能夠工作,但是在爲RijndaelManaged創建IV時遇到了一些錯誤。玩弄C#加密

這是PowerShell代碼工作正常,從互聯網

function Decrypt-String($Encrypted, $Passphrase, $salt, $init="Yet another key") 
{ 
    if($Encrypted -is [string]){ 
     $Encrypted = [Convert]::FromBase64String($Encrypted) 
    } 
    $r = new-Object System.Security.Cryptography.RijndaelManaged 
    $pass = [System.Text.Encoding]::UTF8.GetBytes($Passphrase) 
    $salt = [System.Text.Encoding]::UTF8.GetBytes($salt) 

    $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 

    $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash([Text.Encoding]::UTF8.GetBytes($init))[0..15] 

    $d = $r.CreateDecryptor() 
    $ms = new-Object IO.MemoryStream @(,$Encrypted) 
    $cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" 

    $sr = new-Object IO.StreamReader $cs 
    Write-Output $sr.ReadToEnd() 
    $sr.Close() 
    $cs.Close() 
    $ms.Close() 
    $r.Clear() 
} 

拉,這是C#代碼我把它交給

public static string Decrypt_String(string cipherText, string passPhrase, string Salt) 
{ 
    string hashAlgorithm = "SHA1"; 
    int passwordIterations = 5; 
    initName = "Yet another key"; 
    using (RijndaelManaged r = new RijndaelManaged()) 
    { 
     byte[] cipherTextBytes = Convert.FromBase64String(cipherText); 
     byte[] PassPhraseBytes = Encoding.UTF8.GetBytes(passPhrase); 
     byte[] SaltBytes = Encoding.UTF8.GetBytes(Salt); 
     byte[] initVectorBytes = Encoding.UTF8.GetBytes(initName); 

     PasswordDeriveBytes password = new PasswordDeriveBytes(PassPhraseBytes,SaltBytes,hashAlgorithm,passwordIterations); 
     byte[] keyBytes = password.GetBytes(32); //(256/32) 
     r.Key = keyBytes; 

     SHA1Managed cHash = new SHA1Managed(); 
     r.IV = cHash.ComputeHash(Encoding.UTF8.GetBytes(initName),0,16); 

     ICryptoTransform decryptor = r.CreateDecryptor(); 
     MemoryStream memoryStream = new MemoryStream(cipherTextBytes); 
     CryptoStream cryptoStream = new CryptoStream(memoryStream, 
                decryptor, 
                CryptoStreamMode.Read); 
     StreamReader streamReader = new StreamReader(cryptoStream); 
     string output = streamReader.ReadToEnd(); 
     return output; 
    } 


} 

目前ComputeHash咳回一個錯誤告訴我這個值是無效的。 這裏是我從工作加密函數

密文= 「s6ZqNpJq05jsMh2 + 1BxZzJQDDiJGRQPqIYzBjYQHsgw =」

saltValue = 「} = [BJ8%)vjJDnQfmvC))))3Q」

密碼使用數值=「S @ lt3d」

關於爲什麼IV不會正確設置的任何想法?

編輯:通用

+0

例外。 – Wug

+1

在PS中你有'ComputeHash(...)[0..15]',但你的C#是'ComputeHash(... 0,16)'可能是一個開始的地方? – Nate

+0

更新了抱歉! @Nate我相信他們都應該抓住前16條信息。在C#中,0是開始位置,16是powershell中它剛剛抓取的前16位的數量。 –

回答

2

@Nate的 對不起的例外是

Line 38:    r.IV = cHash.ComputeHash(initVectorBytes, 0, 16); 

Exception Details: System.ArgumentException: Value was invalid. 

一種是正確的,你正在使用的ComputeHash方法的不同過載,並且您還沒有完全處理得當:

Encoding.UTF8.GetBytes(initName) 

這將返回一個字節數組長度相同的字符串 - 。但是通過傳遞016,您要求ComputeHash使用陣列的第一個元素。

cHash.ComputeHash(Encoding.UTF8.GetBytes(initName),0,16); 

所以這第一個修復方法是通過015(或者0initName.Length),或者更好的是,回到你正在使用你的PowerShell腳本可以自動計算出數組的長度過載, :

cHash.ComputeHash(Encoding.UTF8.GetBytes(initName)); 

但你需要縮短所產生的陣列(它回來長度20,但你只想要16):

using System.Linq; 
... 
cHash.ComputeHash(Encoding.UTF8.GetBytes(initName)).Take(16).ToArray(); 
+0

這正是答案!對不起@Nate的快速解僱,認爲它是做同樣的事情!最初將其設置爲0,15或initName.Length將我帶回原始問題,即沒有爲IV準備適當的塊大小。以前16個字節完美工作,這是對超載的誤解。 另外,您是否在賽門鐵克論壇上有類似的名稱? –

+0

很高興我可以幫助(隨時upvote和/或標記爲答案:)。我沒有參加任何賽門鐵克論壇,但我一直在Microsoft TechNet論壇上(用戶名「Lincoln Atkinson」)。 – latkin

+0

只是最終加入,並讓我的聲望上升之前,它允許我upvote,但我絕對會!認爲這是我atkin,誰是賽門鐵克論壇上非常活躍的人,woops!非常感謝 –