I have some text, encrypted by C#'s AesManaged, which must be decrypted in a WinRT Metro application. I cannot change the Encryption code, as the code has other dependencies which cant be changed.
The encryption function looks like this:
// Note: Edited out possibly real password and salt:
Guid password = Guid.Parse("AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA");
Guid salt = Guid.Parse("AAAAAAAAA-BBBB-BBBB-BBBB-AAAAAAAAAAAA");
string EncryptedValue(string data)
{
byte[] passwordBytes = password.ToByteArray();
byte[] saltBytes = salt.ToByteArray();
byte[] bKey = new byte[16];
for(int i = 0; i < 16; i++)
{
bKey[i] = passwordBytes[i];
}
string encryptedData = String.Empty;
using (System.Security.Cryptography.AesManaged aesAlg = new System.Security.Cryptography.AesManaged())
{
aesAlg.Key = bKey;
aesAlg.IV = saltBytes;
// Create a decrytor to perform the stream transform.
System.Security.Cryptography.ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (System.Security.Cryptography.CryptoStream csEncrypt = new System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(data);
}
encryptedData = Convert.ToBase64String(msEncrypt.ToArray());
}
}
}
return encryptedData;
}
Example data:
// Decrypted value is: 2029
var _id = EncryptedSettingsBase.Decrypt("ROSNJ1XnAozF7LC0wW8AOg==");
I read the following post: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/7cfcc576-1c2c-4a50-a546-09a45d3ff41f which looks like the same issue, however I haven't been able to get their suggestion to work, as I get the exception: 'Data error (cyclic redundancy check). (Exception from HRESULT: 0x80070017)'.
internal class EncryptedSettingsBase
{
public static string Decrypt(string cipherText)
{
var passwordBytes = (new Guid("AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")).ToByteArray();
var salt = (new Guid("AAAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA")).ToString();
byte[] bKey = new byte[16];
for (int i = 0; i < 16; i++)
{
bKey[i] = passwordBytes[i];
}
IBuffer pwBuffer = CryptographicBuffer.CreateFromByteArray(bKey);
IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf16LE);
IBuffer cipherBuffer = CryptographicBuffer.DecodeFromBase64String(cipherText);
// Derive key material for password size 32 bytes for AES256 algorithm
KeyDerivationAlgorithmProvider keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
// using salt and 1000 iterations
KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);
// create a key based on original key and derivation parmaters
CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);
CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);
// derive buffer to be used for encryption salt from derived password key
IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);
// display the keys - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately
string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial);
string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial);
SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
// create symmetric key from derived password material
CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);
// encrypt data buffer using symmetric key and derived salt material
IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey, cipherBuffer, saltMaterial);
string result = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf16LE, resultBuffer);
return result;
}
}
I'm probably doing something dumb, but I don't completely understand this stuff. Anyone know where I'm going wrong?
Any help is much appreciated.
Cheers, Jon
You are using PBKDF2 on one side and no PBKDF2 in the .net part. Unfortunately the part that you cannot change does not use the key correctly; it simply uses the UID directly.
The following code does the trick if I could change all my dependencies to encrypt properly:
Code here helped: http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2966549-make-equal-aesmanaged-snippet-as-in-silverlight-an
Encryption code, C# 4.0 side:
string salt = "AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA";
string password = "AAAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA";
string EncryptedValue(string data)
{
byte[] saltBytes = System.Text.Encoding.UTF8.GetBytes(salt);
string encryptedData = String.Empty;
using (System.Security.Cryptography.AesManaged aes = new System.Security.Cryptography.AesManaged())
{
var rfc = new System.Security.Cryptography.Rfc2898DeriveBytes(password, saltBytes);
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
aes.Key = rfc.GetBytes(32);
rfc.Reset();
aes.IV = rfc.GetBytes(16);
// Create a decrytor to perform the stream transform.
System.Security.Cryptography.ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (System.Security.Cryptography.CryptoStream csEncrypt = new System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
// Write all data to the stream.
swEncrypt.Write(data);
}
encryptedData = Convert.ToBase64String(msEncrypt.ToArray());
}
}
}
return encryptedData;
}
Decryption code WinRT side:
protected string Decrypt(string encryptedData)
{
const string password = "AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA";
const string salt = "AAAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA";
IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8);
IBuffer cipherBuffer = CryptographicBuffer.DecodeFromBase64String(encryptedData);
KeyDerivationAlgorithmProvider keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);
CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);
CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);
IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);
SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);
IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey, cipherBuffer, saltMaterial);
byte[] asd;
CryptographicBuffer.CopyToByteArray(resultBuffer, out asd);
string result = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, resultBuffer);
return result;
}
User contributions licensed under CC BY-SA 3.0