1

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

2
  • 1
    In PS you have ComputeHash(...)[0..15] but your C# is ComputeHash(...0,16) might be a place to start? Commented Aug 29, 2012 at 16:35
  • updated sorry! @Nate I believe they should both grab the first 16 pieces of information. in C# the 0 is the start position and the 16 is the amount where in powershell its just grabbing the first 16. Commented Aug 29, 2012 at 16:56

1 Answer 1

2

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

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();
Sign up to request clarification or add additional context in comments.

4 Comments

This was exactly the answer! Sorry @Nate for the quick dismissal, thought it was doing the same exact thing! Initially setting it to 0,15 or initName.Length brought me back to my original problem of not having the proper block size for the IV. Taking the first 16 bytes worked perfectly and it was a misunderstanding of the overload. Also, do you have a similar name on Symantec forums?
Glad I could help (feel free to upvote and/or mark as answer :). I don't go on any Symantec forums, but I have been on the Microsoft TechNet forums for a while (username "Lincoln Atkinson").
Just finally joined, and getting my reputation up before it allows me to upvote, but I definitely will! Thought it was I atkin, who is a guy very active on Symantec forums, woops! Thanks a lot
Welcome to the community! It takes rep to upvote, but you can still mark as answer (the little checkbox) :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.