Reputation: 369
I have a little problem with the whole encrypt/decrypt cr*p ;-)
Is it possible to decrypt data in WinRt (Windows Store App) which was encrypted in a .NET Desktop Application and vice versa? I cannot change the code of the Desktop App because it is already in use.
I already tried a few tutorials for the CryptographicEngine in WinRT but I never get results which match with the ones from the Desktop App.
Maybe somebody could help me? I'm very new to .NET development and I never really did anything with Encryption so I have no idea what I'm doing ;-)
Here is some of the code used in the Desktop App - I can't change that code!
private string pwd = "password";
private string salt = "salt";
public byte[] Encrypt(byte[] data)
{
PasswordDeriveBytes derivedPassword = new PasswordDeriveBytes(pwd, Encoding.ASCII.GetBytes(salt));
byte[] key = derivedPassword.GetBytes(16);
byte[] iv = Encoding.ASCII.GetBytes("1234567891234567");
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
byte[] cipherBytes = null;
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(key, iv))
{
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
cipherBytes = ms.ToArray();
ms.Close();
}
}
}
symmetricKey.Clear();
return cipherBytes;
}
Here an example method that I tried in WinRT - but the result was different to that from the Desktop App (Most of the code is from http://blog.lordinaire.fr/2012/12/winrt-encryption-and-decryption-with-aes-algorithm/ )
non functioning code was removed - see edit
I would really apreciate some help
greetings from Austria
Edit I tried a few things, but I still could not get it to work right :( I just can't get the right key. To test the encryption nonetheless, I hardcoded the key - then it works.
Like Nate Diamond suggested, I used the KeyDerivationAlogrithm with an empty salt and an already salted password. One problem is, I don't know how "to salt". I tried putting the salt in front, at the end, in the middle and alternating every symbol - still not the right key :( Here the code I was using:
// password = 11112222333344445555 // salt = aaaabbbbccccddddeeee
private string password = "11112222333344445555aaaabbbbccccddddeeee";
private byte[] salt = new byte[20];
private uint iterationCount = 100;
private static byte[] keyBytes = null;
public static byte[] KeyBytes
{
get
{
//for (int i = 0; i < salt.Length; i++)
//{
// salt[i] = 0;
//}
// Setup KDF parameters for the desired salt and iteration count
KeyDerivationParameters kdfParameters = KeyDerivationParameters.BuildForPbkdf2(CryptographicBuffer.CreateFromByteArray(salt), iterationCount);
// Get a KDF provider for PBKDF2, and store the source password in a Cryptographic Key
KeyDerivationAlgorithmProvider kdf = KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha1);
IBuffer passwordBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
CryptographicKey passwordSourceKey = kdf.CreateKey(passwordBuffer);
// Generate key material from the source password, salt, and iteration count. Only call DeriveKeyMaterial once,
// since calling it twice will generate the same data for the key and IV.
uint totalDataNeeded = 16;
IBuffer keyAndIv = CryptographicEngine.DeriveKeyMaterial(passwordSourceKey, kdfParameters, totalDataNeeded);
// Split the derived bytes into a seperate key and IV
keyBytes = keyAndIv.ToArray();
return keyBytes;
}
}
Here the code of my encrypt method - it yields the same result as the one in the .NET Desktop App :)
private byte[] btVector = Encoding.UTF8.GetBytes("1234567891234567");
private byte[] keyBytes = Encoding.UTF8.GetBytes("123456789123456789123456");
public byte[] Encrypt(byte[] data)
{
// Get the key and iv and put all into IBuffers
IBuffer keyBuffer = WindowsRuntimeBuffer.Create(KeyBytes, 0, 16, 16); ;
IBuffer iv = WindowsRuntimeBuffer.Create(InitialVectorBytes, 0, 16, 16);
IBuffer plainText = CryptographicBuffer.CreateFromByteArray(data);
byte[] encryptedData;
// Setup an AES key, using AES in CBC mode and applying PKCS#7 padding on the input
SymmetricKeyAlgorithmProvider aesProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
CryptographicKey aesKeySymm = aesProvider.CreateSymmetricKey(keyBuffer);
// Encrypt the data and convert it to byte array
IBuffer encrypted = CryptographicEngine.Encrypt(aesKeySymm, plainText, iv);
CryptographicBuffer.CopyToByteArray(encrypted, out encryptedData);
return encryptedData;
}
Upvotes: 1
Views: 913
Reputation: 5575
PBKDF[1/2] are basically this:
1. Take a password.
2. Add a salt.
3. Hash the combined password and salt. Store in `result`
4. For (number of iterations)
1. Hash `result`, store in `result`.
The big difference between PBKDF1 and PBKDF2 is the first part of step 4. In PBKDF1, it is as printed. In PBKDF2, it changes to this:
4. For (number of iterations)
1. Combine `result` and `salt`. Store in `result`
2. Hash `result`, store in `result`.
So, you have a few options.
Option 1:
Create a custom implementation of PBKDF1. The HashAlgorithmProvider
makes it very easy to repeatedly hash the result.
Option 2:
Use PBKDF2 with an empty salt
byte
array and the combined salt and password as your secret
. This should have the same effect as PBKDF1.
It should be noted that if at all possible, you should probably switch to using PBKDF2.
Hope this helps and happy coding!
Upvotes: 1