我正在尝试将 WP8 应用程序移植到 Win 8.1 商店应用程序。该应用程序使用基于密码的 AES 256 进行加密。我的困惑是我能够从 WP8 解密文本,使用 256 位密钥加密,但在 Win RT 中只能使用 32 位密钥。
下面是 Window Phone 8 代码。这里注意 Rfc2898DeriveBytes 想要它以字节为单位,所以使用的密钥是 256 位。
private static string Decrypt(string dataToDecrypt, string password, string salt)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
try
{
//Generate a Key based on a Password and HMACSHA1 pseudo-random number generator
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 10000);
//Create AES algorithm
aes = new AesManaged();
aes.KeySize = aes.LegalKeySizes[0].MaxSize; // returns 256
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize; // return 128
aes.Key = rfc2898.GetBytes(aes.KeySize);
aes.IV = rfc2898.GetBytes(aes.BlockSize);
//Create Memory and Crypto Streams
memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write);
//Decrypt Data
byte[] data = Convert.FromBase64String(dataToDecrypt);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
//Return Decrypted String
byte[] decryptBytes = memoryStream.ToArray();
//Dispose
if (cryptoStream != null)
cryptoStream.Dispose();
//Retval
return Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
}
catch (Exception ex)
{
MasterData.CryptographyExceptionOccured = true;
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
return "";
}
finally
{
if (memoryStream != null)
memoryStream.Dispose();
if (aes != null)
aes.Clear();
}
}
下面是 Win RT 代码 (Win 8.1) 这里请注意 CryptographicEngine.DeriveKeyMaterial 方法需要密钥大小(以位为单位)。但我可以使用下面的 Win RT 代码解密 WP8 中的 256 位加密,这似乎只使用 32 位。(在 WP8/Win RT 中使用的密码和盐是一样的)
private static void GenerateKeyMaterial(string password, string salt, uint iterationCount, out IBuffer keyMaterial, out IBuffer iv)
{
// Setup KDF parameters for the desired salt and iteration count
IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8);
KeyDerivationParameters kdfParameters = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, iterationCount);
// Get a KDF provider for PBKDF2, and store the source password in a Cryptographic Key
KeyDerivationAlgorithmProvider kdf = KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha256);
// 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.
int keySize = 256 / 8;
int ivSize = 128 / 8;
uint totalDataNeeded = (uint)(keySize + ivSize);
IBuffer keyAndIv = CryptographicEngine.DeriveKeyMaterial(passwordSourceKey, kdfParameters, totalDataNeeded);
// Split the derived bytes into a seperate key and IV
byte[] keyMaterialBytes = keyAndIv.ToArray();
keyMaterial = WindowsRuntimeBuffer.Create(keyMaterialBytes, 0, keySize, keySize);
iv = WindowsRuntimeBuffer.Create(keyMaterialBytes, keySize, ivSize, ivSize);
}
那么要在 Win RT 中使用 256 位加密,上述代码中的密钥大小应该是多少?如何使用 32 位密钥解密 256 位加密字符串。参见上面的 WP8 和 Win RT 代码。