玩弄 C# 加密 (Playing around with C# encryption)


問題描述

玩弄 C# 加密 (Playing around with C# encryption)

Been trying to venture out and learn some C# and powershell, giving myself little projects to try and learn. Recently I have been trying to convert some code from powershell to C# and I believe I got it working but am coming across some errors creating the IV for RijndaelManaged.

This is the powershell code that works fine, pulled from the internet

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()
}

And this is the C# code i moved it over to

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;
    }


}

Currently the ComputeHash is spitting back an error telling me the value is invalid. here are the values I am using from the working encrypt function

cipherText = "s6ZqNpJq05jsMh2+1BxZzJQDDiJGRQPqIYzBjYQHsgw="

saltValue = "}=[BJ8%)vjJDnQfmvC))))3Q"

passphrase = "S@lt3d"

Any ideas on why the IV wont set properly?

EDIT: Sorry the exception is 

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

Exception Details: System.ArgumentException: Value was invalid.

Kind of generic 

‑‑‑‑‑

參考解法

方法 1:

<p>@Nate is correct, you are using a different overload of the ComputeHash method, and you are not quite handling it properly:</p>

Encoding.UTF8.GetBytes(initName)

This will return a byte array the same length as your string ‑ 15.  But by passing 0 and 16, you are asking ComputeHash to use the first 16 elements of the array.

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

So this first fix is to either pass 0 and 15 (or maybe 0 and initName.Length), or better yet, go back to the overload you are using in your powershell script, which figures out the array length automatically:

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

But you will need to shorten the resulting array (it comes back length 20, but you only want 16):

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

(by s0n‑latkin)

參考文件

  1. Playing around with C# encryption (CC BY‑SA 3.0/4.0)

#powershell #Encryption #C#






相關問題

玩弄 C# 加密 (Playing around with C# encryption)

查找具有特定 startname 的特定服務 (Finding specific services with specific startname)

試圖從事件日誌中獲取數據到電子郵件中的 html (Trying to get data from event logs into html in email)

如何通過powershell獲取請求的authtoken (How to obtain authtoken for request via powershell)

如何在錯誤時繼續使用 &$var 調用可執行文件 (How to continue on error a call to an executable using &$var)

在同一範圍內從 c# 調用多個 powershell 命令 (Invoke multiple powershell commands from c# on the same scope)

如何在 Powershell 二進制模塊(.Net Standard 和 Nuget)中處理公共和私有依賴項和打包 (How to handle public and private dependencies and packaging in Powershell binary module (.Net Standard & Nuget))

如何使用參數(描述空白)獲取廣告中的所有 OU - 沒有描述? (How to get all OU in Ad with parameter (description blank ) - without description?)

遠程服務器返回錯誤:(400) 錯誤請求。在 C:\Program Files\WindowsPowerShell\Modules\CosmosDB\3.1.0.293\CosmosDB.psm1 (The remote server returned an error: (400) Bad Request. At C:\Program Files\WindowsPowerShell\Modules\CosmosDB\3.1.0.293\CosmosDB.psm1)

Powershell 檢查文件類型 (Powershell check file type)

服務器待重啟 (Server Pending Reboot)

PowerShell 的 Invoke-WebRequest 在 Docker 容器中不起作用 (PowerShell's Invoke-WebRequest not working within a Docker Container)







留言討論