Шифрование CryptoJs и дешифрование C# с использованием RijndaelManaged - Ошибка
У меня есть клиентское шифрование файлов в javascript с использованием CryptoJs. У меня есть расшифровка файла на стороне сервера с помощью RijndaelManaged. Если я делаю шифрование и дешифрование с помощью CryptoJs, это работает нормально. Тем не менее, когда я пытаюсь расшифровать с помощью кода C#, он выдает ошибку ниже. Я пытался установить различные отступы, режимы и т. Д. Безрезультатно.
CryptographicException length of the data to decrypt is invalid
Код CRyptoJS:
function encryptFile() {
selectedFiles = document.getElementById("MainContent_fileinput");
$.each(selectedFiles.files, function (i, file) {
var reader = new FileReader();
var strKey = " ";
var strIv = " ";
var byteArrKey = [169,204,147,221,70,76,207,92,102,12,237,65,5,205,34,106,178,141,138,117,224,153,37,124,54,17,74,223,224,153,72,209];
var byteArrIV = [169,204,147,221,70,76,207,92,102,12,237,65,5,205,34,106];
var byteVal;
var byteValIv;
reader.onloadend = function (e) {
for (var i = 0; i < byteArrKey.length; i++) {
byteVal = byteArrKey[i];
if (byteVal < 16) { strKey += "0"; }
strKey += byteVal.toString(16);
};
for (var i = 0; i < byteArrIV.length; i++) {
byteValIv = byteArrIV[i];
//if (byteValIv < 16) { strIv += "0"; }
strIv += byteVal.toString(16);
};
var encrypted1 = CryptoJS.AES.encrypt(reader.result, strKey, { 'iv': strIv });
// var encrypted1 = CryptoJS.AES.encrypt(reader.result, key,
// { keySize: 128 / 8, iv: iv1, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
var ct1 = encrypted1.toString();
var encodedData1 = window.btoa(ct1);
$.ajax({
async: 'true',
url: "MYWEBSERVICE URL",
method: "POST",
processData: 'false',
headers: {
'content-type': "application/x-www-form-urlencoded",
'cache-control': "no-cache"
},
data: { 'folderPath': folderPath, 'uploadData': encodedData1, 'fileName': file.name + '.encrypted' },
success: function (response) {
debugger;
console.log(response);
},
error: function (xhr, textStatus, error) {
debugger;
console.log(xhr.statusText);
}
});
};
reader.readAsDataURL(file);
})
}
Расшифровка с использованием C#:
private static byte[] CreateKey(string pwd)
{
byte[] bytKey;
byte[] bytSalt = Encoding.ASCII.GetBytes(pwd);
PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwd, bytSalt);
bytKey = pdb.GetBytes(32);
return bytKey;
}
private static byte[] CreateIV(string pwd)
{
byte[] bytIV;
byte[] bytSalt = Encoding.ASCII.GetBytes(pwd);
PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwd, bytSalt);
bytIV = pdb.GetBytes(16);
return bytIV;
}
private static bool DecryptFile(string strInputFile, string strOutputFile)
{
bool returnValue = true;
FileStream fsInput = null;
FileStream fsOutput = null;
Int32 intBytesInCurrentBlock;
CryptoStream csCryptoStream = null;
byte[] bytBuffer; // = new byte[fsInput.Length];
bytKey = CreateKey("123456");
bytIV = CreateIV("123456");
try
{
using (var fsInput = File.OpenRead(strInputFile))
using (var fsOutput = File.Create(strOutputFile))
using (Aes aes = Aes.Create())
using (ICryptoTransform decryptor = aes.CreateDecryptor(bytKey, bytIV))
using (var decryptionStream = new CryptoStream(fsOutput, decryptor, CryptoStreamMode.Write))
using (var base64Decode = new FromBase64Transform())
using (var cryptoStream = new CryptoStream(decryptionStream, base64Decode, CryptoStreamMode.Write))
{
fsInput.CopyTo(cryptoStream);
cryptoStream.Dispose();
cryptoStream.FlushFinalBlock();
decryptionStream.Dispose();
decryptionStream.FlushFinalBlock();
}
}
catch
{
throw;
}
finally
{
csCryptoStream.Close();
fsInput.Close();
fsOutput.Close();
}
return returnValue;
}
Метод WebService:
byte[] byteUploadFile = Convert.FromBase64String(uploadData);
BinaryWriter binWriter = new BinaryWriter(File.Open(Path.Combine(folderPath, fileName), FileMode.Create, FileAccess.ReadWrite));
binWriter.Write(byteUploadFile);
binWriter.Close();
2 ответа
Решено, как показано ниже:
Шифрование файлов с использованием CryptoJS:
function esp() {
selectedFiles = document.getElementById("MainContent_file1");
var sfile = selectedFiles.files[0];
var read = new FileReader();
read.onload = function (e) {
var key = CryptoJS.enc.Utf8.parse('7061737323313233');
var iv = CryptoJS.enc.Utf8.parse('7061737323313233');
var encrypted = CryptoJS.AES.encrypt(reader.result, key, { keySize: 128 / 8, iv: iv,
mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7
});
var ct = encrypted.toString();
debugger;
$.ajax({
async: 'true',
url: "http://localhost:51936/WebService1.asmx/FileUpload",
method: "POST",
processData: 'false',
headers: {
'content-type': "application/json",
'cache-control': "no-cache"
},
data: JSON.stringify({ 'folderPath': folderPath, 'uploadData': ct, 'fileName': sfile.name + '.encrypted' }),
success: function (response) {
console.log(response);
},
error: function (xhr, textStatus, error) {
console.log(xhr.statusText);
}
});
}
read.readAsDataURL(sfile);
}
Расшифровка с использованием C#:
[WebMethod]
public void Decrypt(object sender, EventArgs e)
{
string folderPath = "path";
DirectoryInfo d = new DirectoryInfo(folderPath).GetDirectories().OrderByDescending(ds => ds.LastWriteTimeUtc).First();
try
{
foreach (FileInfo file in d.GetFiles())
{
string plaintext = "";
string filename = file.Name;
byte[] cipherText = new byte[file.Length];
FileStream fs = file.OpenRead();
fs.Read(cipherText, 0, (int)file.Length);
byte[] keybytes = Encoding.UTF8.GetBytes("7061737323313233");
byte[] iv = Encoding.UTF8.GetBytes("7061737323313233");
MyWebService.MyWebServicedts = new MyWebService.MyWebService();
using (var rijAlg = new RijndaelManaged())
{
rijAlg.Mode = CipherMode.CBC;
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.FeedbackSize = 128;
rijAlg.Key = keybytes;
rijAlg.IV = iv;
var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
plaintext = plaintext.Substring(23);
string name = filename.Substring(filename.LastIndexOf("/") + 1);
name = name.Replace(".encrypted", "");
dts.FileUpload(folderPath, plaintext, name);
}
}
catch (Exception ex)
{
string err = ex.Message;
}
}
Веб-сервис для сохранения данных в виде файла на сервере:
byte[] byteUploadFile = Convert.FromBase64String(uploadData);
BinaryWriter binWriter = new BinaryWriter(File.Open(Path.Combine(folderPath, fileName), FileMode.Create, FileAccess.ReadWrite));
binWriter.Write(byteUploadFile);
binWriter.Close();
Из javascript вы, кажется, записываете в файл вывод window.btoa(ct1)
, который в кодировке Base64. В C# вы читаете содержимое файла как двоичные данные.
Легко читать:
string base64 = File.ReadAllText(strInputFile);
byte[] decoded = Convert.FromBase64String(base64);
using (Aes aes = Aes.Create())
using (ICryptoTransform decryptor = aes.CreateDecryptor(bytKey, bytIV))
using (var fsOutput = File.Create(strOutputFile))
using (var cryptoStream = new CryptoStream(fsOutput, decryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(decoded, 0, decoded.Length);
}
Лучшая производительность (особенно для больших данных):
using (var fsInput = File.OpenRead(strInputFile))
using (var fsOutput = File.Create(strOutputFile))
using (Aes aes = Aes.Create())
using (ICryptoTransform decryptor = aes.CreateDecryptor(bytKey, bytIV))
using (var decryptionStream = new CryptoStream(fsOutput, decryptor, CryptoStreamMode.Write))
using (var base64Decode = new FromBase64Transform())
using (var cryptoStream = new CryptoStream(decryptionStream, base64Decode, CryptoStreamMode.Write))
{
fsInput.CopyTo(cryptoStream);
}
Во втором примере поток данных:
fsInput.CopyTo(cryptoStream) ->
read some data from fsInput
write data to cryptoStream
Base64Decode the data in progress
write decoded data to decryptionStream
decrypt the data in progress
write decrypted to fsOutput
loop until reading says it's out of data.
Тогда на }
(вызывая Dispose на всех в обратном порядке)
cryptoStream.Dispose() -> cryptoStream.FlushFinalBlock() ->
base64Decode will throw if there's bad data remaining
decryptionStream.Dispose() -> decryptionStream.FlushFinalBlock() ->
throw if padding is bad, otherwise write the final block to fsOutput