2017-01-17 15 views
0

У меня есть шифрование файлов на стороне клиента в javascript с использованием CryptoJs. У меня есть расшифровка файла на стороне сервера с помощью RijndaelManaged. Если я использую шифрование и дешифрование с помощью CryptoJs, он работает нормально. Однако, когда я пытаюсь расшифровать код C#, он бросает ошибку ниже. Я пробовал устанавливать различные прокладки, режимы и т. Д., Но безрезультатно.Шифрование CryptoJs и дешифрование C# с использованием RijndaelManaged - Ошибка

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(); 

ответ

0

Решено, как показано ниже:

шифрования файлов с помощью 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; 
    } 
} 

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(); 
0

Из JavaScript Вы, кажется, записать в файл на выходе window.btoa(ct1), w он кодируется 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 
+0

Итак, я добавил код в ваше предложение, см. 'DecryptFile()' в исходном вопросе. Теперь я получаю ** Заполнение недопустимым и не может быть удалено ** ошибка. – Noob

+0

Кроме того, я добавил webservice mehtod, который я использую для создания/сохранения файла на сервере. Похоже, Bsae64 преобразуется в двоичный файл при записи в файл. – Noob

+0

Я также добавил это 'aes.Padding = PaddingMode.Zeros;'. Теперь ошибка исчезла. Однако дешифрованный файл не такой же, как у оригинала. Исходный файл: 4KB, ecnrypted: 7KB, расшифрованный: 5KB. – Noob