CryptoJS.AES.encrypt(text, password)
неявно получает ключ шифрования и iv из вашего пароля, используя алгоритм деривации, который не является родным для C #. Вместо того, чтобы полагаться на этот неявный вывод - лучше явно сделать это самостоятельно, используя хорошо известный алгоритм, такой как PBKDF2.
Получение ключа необходимо, поскольку ваш пароль может иметь произвольный размер, но для данного алгоритма (AES) требуется ключ определенного размера, например, 256 бит. Поэтому нам нужно перейти от пароля произвольной длины к ключу фиксированного размера (необратимым образом).
Пример кода JavaScript:
function encrypt (msg, pass) {
// random salt for derivation
var keySize = 256;
var salt = CryptoJS.lib.WordArray.random(16);
// well known algorithm to generate key
var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: 100
});
// random IV
var iv = CryptoJS.lib.WordArray.random(128/8);
// specify everything explicitly
var encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
// combine everything together in base64 string
var result = CryptoJS.enc.Base64.stringify(salt.concat(iv).concat(encrypted.ciphertext));
return result;
}
Расшифровка в C # теперь проста:
public static string Decrypt(string cipherText, string password) {
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create()) {
// extract salt (first 16 bytes)
var salt = cipherBytes.Take(16).ToArray();
// extract iv (next 16 bytes)
var iv = cipherBytes.Skip(16).Take(16).ToArray();
// the rest is encrypted data
var encrypted = cipherBytes.Skip(32).ToArray();
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, salt, 100);
encryptor.Key = pdb.GetBytes(32);
encryptor.Padding = PaddingMode.PKCS7;
encryptor.Mode = CipherMode.CBC;
encryptor.IV = iv;
// you need to decrypt this way, not the way in your question
using (MemoryStream ms = new MemoryStream(encrypted)) {
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Read)) {
using (var reader = new StreamReader(cs, Encoding.UTF8)) {
return reader.ReadToEnd();
}
}
}
}
}
Если вы понимаете последствия, вы можете использовать фиксированную соль (или, например, фиксированную соль на пользователя в вашем приложении) и сократить количество итераций в PBKDF2. Однако не используйте фиксированный IV и не используйте часть ключа в качестве IV.