当我尝试将我的项目从Windows Phone Silverlight 8.1移植到Windows运行时,我遇到了阻塞问题。 在Windows运行时中,AES加密的字符串与Silverlight之前的字符串不同。
在Silverlight中:
public static string EncryptAES(string encryptString)
{
AesManaged aes = null;
MemoryStream ms = null;
CryptoStream cs = null;
string encryptKey = "testtest123";
string salt = "abcabcabcd";
try
{
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(encryptKey, Encoding.UTF8.GetBytes(salt));
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);
ms = new MemoryStream();
cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
byte[] data = Encoding.UTF8.GetBytes(encryptString);
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
catch
{
return encryptString;
}
finally
{
if (cs != null)
cs.Close();
if (ms != null)
ms.Close();
if (aes != null)
aes.Clear();
}
}
在Windows运行时:
public static string EncryptAES(string plainText)
{
string pw = "testtest123";
string salt = "abcabcabcd";
IBuffer plainBuffer = CryptographicBuffer.ConvertStringToBinary(plainText, BinaryStringEncoding.Utf8);
IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8);
IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(pw, BinaryStringEncoding.Utf8);
KeyDerivationAlgorithmProvider keyDerivationProvider = Windows.Security.Cryptography.Core.KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha256);
// 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 buffers - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately
string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial);
string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial);
//AES_CBC_PKCS7
SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
// create symmetric key from derived password key
CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);
// encrypt data buffer using symmetric key and derived salt material
IBuffer resultBuffer = CryptographicEngine.Encrypt(symmKey, plainBuffer, saltMaterial);
string result = CryptographicBuffer.EncodeToBase64String(resultBuffer);
return result;
}
在Silverlight项目中,AES加密的字符串“123456”为“4UfdhC / 0MFQlMhl7N7gqLg ==”; 在Windows运行时项目中,AES加密的字符串是“jxsR5EuhPXgRsHLs4N3EGQ ==”
那么如何才能在WinRT上获得与Silverlight相同的字符串?
答案 0 :(得分:1)
AES类默认为Microsoft运行时的随机IV。要获得相同的密文,您需要使用静态IV。然而,这并不安全。相反,您应该检查是否获得相同的关键字节,并让每次运行的密文不同。否则你可以清楚地区分相同的明文。
您似乎也使用了错误的哈希算法,Rfc2898DeriveBytes
使用SHA-1而不是SHA-256作为基础哈希函数。
答案 1 :(得分:0)
我已经创建了一个适合我作为System.Security.Cryptography.Rfc2898DeriveBytes替换的课程:
public class Rfc2898DeriveBytes
{
private readonly string _password;
private readonly byte[] _salt;
public Rfc2898DeriveBytes(string password, byte[] salt)
{
_password = password;
_salt = salt;
IterationCount = 1000;
}
public uint IterationCount { get; set; }
public byte[] GetBytes(uint cb)
{
var provider = KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha1);
var buffSecret = CryptographicBuffer.ConvertStringToBinary(_password, BinaryStringEncoding.Utf8);
var buffsalt = CryptographicBuffer.CreateFromByteArray(_salt);
var keyOriginal = provider.CreateKey(buffSecret);
var par = KeyDerivationParameters.BuildForPbkdf2(buffsalt, IterationCount);
var keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, par, cb);
byte[] result;
CryptographicBuffer.CopyToByteArray(keyMaterial, out result);
return result;
}
}