1

I've been ask to do a task in a project that involves encryption on a windows 8.

The scenario is something like this:

I get a byte[] from a server, the first 16 bytes are the IV, the next 128 are the Salt and the remaining ones are the File itself.

The user then provides a password and with that and the salt i should create a PKCS5 Key with 40 iterations and the key should have 32bytes length.

Right now i've splitted the byte[] in th 3 i require, but i dont know how the rest is done in windows C#.

Thought
  • 5,326
  • 7
  • 33
  • 69

2 Answers2

7

I've done some work with encryption/decryption, but let me give you the resource I used for AES 256 bit encryption. Hopefully this will give you an idea of how to switch it over to PKCS5, but everything else I'm pretty sure is the same. It's a little lengthy, but let me know if this applies to your situation. I'm curious how much different it would be for PKCS5 instead of AES256.

Edit: Because the code they posted wasn't clear on the iterations, the iterations is controlled by the line var key = Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); using 1000 iterations.

http://www.codeproject.com/Articles/769741/Csharp-AES-bits-Encryption-Library-with-Salt

Core Encryption Code

using System.Security.Cryptography;
using System.IO;

Encryption

public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
    byte[] encryptedBytes = null;

    // Set your salt here, change it to meet your flavor:
    // The salt bytes must be at least 8 bytes.
    byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

    using (MemoryStream ms = new MemoryStream())
    {
        using (RijndaelManaged AES = new RijndaelManaged())
        {
            AES.KeySize = 256;
            AES.BlockSize = 128;

            var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
            AES.Key = key.GetBytes(AES.KeySize / 8);
            AES.IV = key.GetBytes(AES.BlockSize / 8);

            AES.Mode = CipherMode.CBC;

            using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                cs.Close();
            }
            encryptedBytes = ms.ToArray();
        }
    }

    return encryptedBytes;
}

Decryption

public byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
    byte[] decryptedBytes = null;

    // Set your salt here, change it to meet your flavor:
    // The salt bytes must be at least 8 bytes.
    byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

    using (MemoryStream ms = new MemoryStream())
    {
        using (RijndaelManaged AES = new RijndaelManaged())
        {
            AES.KeySize = 256;
            AES.BlockSize = 128;

            var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
            AES.Key = key.GetBytes(AES.KeySize / 8);
            AES.IV = key.GetBytes(AES.BlockSize / 8);

            AES.Mode = CipherMode.CBC;

            using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                cs.Close();
            }
            decryptedBytes = ms.ToArray();
        }
    }

    return decryptedBytes;
}

Getting Randomized Encryption Result with Salt

If we encrypt the same context (i.e. string of "Hello World") for 10 times, the encrypted results will be the same. What if we want the results different from each time it is encrypted?

What I do is appending a random salt bytes in front of the original bytes before encryption, and remove it after decryption.

Example of Appending Randomized Salt Before Encrypting a String

public string Encrypt(string text, string pwd)
{
    byte[] originalBytes = Encoding.UTF8.GetBytes(text);
    byte[] encryptedBytes = null;
    byte[] passwordBytes = Encoding.UTF8.GetBytes(pwd);

    // Hash the password with SHA256
    passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

    // Generating salt bytes
    byte[] saltBytes = GetRandomBytes();

    // Appending salt bytes to original bytes
    byte[] bytesToBeEncrypted = new byte[saltBytes.Length + originalBytes.Length];
    for (int i = 0; i < saltBytes.Length; i++)
    {
        bytesToBeEncrypted[i] = saltBytes[i];
    }
    for (int i = 0; i < originalBytes.Length; i++)
    {
        bytesToBeEncrypted[i + saltBytes.Length] = originalBytes[i];
    }

    encryptedBytes = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

    return Convert.ToBase64String(encryptedBytes);
}

Example of Removing the Salt after Decryption

public string Decrypt(string decryptedText, string pwd)
{
    byte[] bytesToBeDecrypted = Convert.FromBase64String(decryptedText);
    byte[] passwordBytes = Encoding.UTF8.GetBytes(pwd);

    // Hash the password with SHA256
    passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

    byte[] decryptedBytes = AES_Decrypt(bytesToBeDecrypted, passwordBytes);

    // Getting the size of salt
    int _saltSize = 4;

    // Removing salt bytes, retrieving original bytes
    byte[] originalBytes = new byte[decryptedBytes.Length - _saltSize];
    for (int i = _saltSize; i < decryptedBytes.Length; i++)
    {
        originalBytes[i - _saltSize] = decryptedBytes[i];
    }

    return Encoding.UTF8.GetString(originalBytes);
}

Code for getting random bytes

public byte[] GetRandomBytes()
{
    int _saltSize = 4;
    byte[] ba = new byte[_saltSize];
    RNGCryptoServiceProvider.Create().GetBytes(ba);
    return ba;
}
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
dakre18
  • 181
  • 7
  • 1
    Read the last line he posted `Right now i've splitted the byte[] in th 3 i require, but i dont know how the rest is done in windows C#.` which tells me he has the bytes split into the 3 pieces, but he doesn't know how to encrypt/decrypt them using the IV, salt, and file. Also I didn't copy the entire article, just the parts relevant to his question. When i've posted without quoting the parts of the article that are relevant, i'm told to quote it in case something happens to it later. – dakre18 Oct 06 '15 at 15:47
  • I see. It's still not ok. Apart from the formatting problems in your answer, it's frowned upon to answer bad questions. The OP wants somebody to deliver them quite a lot of code without showing what they tried and what didn't work. Stack Overflow should not be a coding service. – Artjom B. Oct 06 '15 at 15:56
  • True, and wouldn't it technically fit better in one of the security or programming stack exchanges instead? That might be helpful for the OP to know. – dakre18 Oct 06 '15 at 16:27
  • 3
    No, I don't think the question would be a better fit for [programmers.se]. It's certainly not fit for [security.se], because the OP is asking for C# code. – Artjom B. Oct 06 '15 at 16:32
  • that example uses the RijndaelManaged wich inst present in windows store apps i think. – Thought Oct 07 '15 at 08:06
  • @Artjom B. I dind't ask for a full code implementation of what i need. I want ppl to point me in the right direction ( like some tutorials ), ofc that if they want to contribute with code examples i wont say no. I guess i should just stick to "how to write hello world" questions, since those are allways answered. – Thought Oct 07 '15 at 08:54
  • I posted this, since this is what i used to get familiar with encrypting in AES256. It was very helpful, because most of the code is commented well enough, that i could learn what it's doing. Unfortunately, i could never find any good tutorials for it, besides abstract theory that doesn't help (at least not me). Another unfortunate thing is that I'm not familiar with PKCS5 to modify the code, but i did find a question that might answer the problem with using RijndaelManaged on https://stackoverflow.com/questions/13199028/windows-security-cryptography-and-windows-phone-8-sdk – dakre18 Oct 08 '15 at 14:30
1

Step 1: Split the incoming data into IV, salt and cyphertext. You say you have done this.

Step 2: Pass the supplied password and the salt from step 1 as inputs to the PKCS5 key generation method, using 40 iterations. There should be a PKCS5 class in your crypto library. The output from this step will be a key.

Step 3: Use the key from step 2 and the IV from step 1 to decrypt the cyphertext from step 1. Use the specified decryption algorithm, probably AES, in the specified mode. Since an IV is supplied then it is likely that CBC mode is intended, so you will probably need to use the AES-CBC mode from your cypher library. Check the problem specification to confirm both algorithm and cypher mode -- I am only guessing here.

If you have a problem with any of these steps, ask here again, showing your code and explaining the errors you are getting.

rossum
  • 15,344
  • 1
  • 24
  • 38
  • What is the crypto library i should use ? – Thought Oct 07 '15 at 12:38
  • 1
    Start with the library built into C#, if there is one. Failing that, talk to your boss/instructor and see what is standard for your work/teaching environment. If there is no standard set then try [Bouncy Castle](http://www.bouncycastle.org/csharp/). – rossum Oct 07 '15 at 12:43