2012-08-29 24 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!非常感谢 –