I’ve been working over the last few days on trying to port the simple encryption (found here) used to log into the Wizards of the Coast Character Builder API (so my app can download a user’s characters directly from the servers) to something I can use in a Windows 8 Metro app, since AesManaged didn’t make it into the Metro cryptography libraries. Seeing as I’m a novice programmer at best, this has proven a bit beyond my skills.
Here’s the code I need to port over:
public static byte[] SimpleEncrypt(string value, string key)
{
byte[] buffer2;
ICryptoTransform transform = GetSimpleAlgorithm(key).CreateEncryptor();
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
stream2.Write(bytes, 0, bytes.Length);
stream2.Flush();
stream2.FlushFinalBlock();
stream.Position = 0L;
buffer2 = stream.ToArray();
}
}
return buffer2;
}
private static SymmetricAlgorithm GetSimpleAlgorithm(string key)
{
AesManaged aes = new AesManaged();
byte[] source = new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(key));
return new AesManaged { Key = source, IV = source.Take<byte>((aes.BlockSize / 8)).ToArray<byte>() };
}
This is used to encrypt the password prior to passing the login:
contentClient.Login(username, SimpleEncrypt(password, username));
And in case it’s needed, the web service is located at: http://ioun.wizards.com/ContentVault.svc
In the comments on that link way up there in the first link, someone suggested some code for Windows 8 back in February, but said code had a few problems I had to fix before it would even compile, and even then, when I try to log in with it, I get an exception back from the service saying “padding is invalid and cannot be removed”.
Here’s what I’m currently working with:
private static byte[] SimpleEncrypt(string value, string key)
{
var simpleAlgorithm = GetSimpleAlgorithm(key);
var encryptedBuffer = CryptographicEngine.Encrypt(simpleAlgorithm.Item1, CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8), simpleAlgorithm.Item2);
var result = new byte[encryptedBuffer.Length];
CryptographicBuffer.CopyToByteArray(encryptedBuffer, out result);
return result;
}
private static Tuple<CryptographicKey, IBuffer> GetSimpleAlgorithm(string key)
{
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var keyAsBinary = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
var source = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256).HashData(keyAsBinary);
var shortKey = CryptographicBuffer.CreateFromByteArray(UTF8Encoding.UTF8.GetBytes(key).Take((int)provider.BlockLength).ToArray());
return new Tuple<CryptographicKey,IBuffer>(provider.CreateSymmetricKey(source), shortKey);
}
Any help getting this working would be EXTREMELY appreciated.
Welp, spent more time looking it over, and figured out the problem.
The suggested updated version was using the “key” string to create the IV, whereas it should have been using the hash of the key, instead.
Here’s the functional version, in case anyone wants it: