CryptoJs加密和使用RijndaelManaged的c#解密 - 错误

时间:2017-01-17 16:32:21

标签: c# encryption cryptography cryptojs rijndaelmanaged

我使用CryptoJs在javascript中进行客户端文件加密。我使用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 个答案:

答案 0 :(得分:0)

从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

答案 1 :(得分: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;
    }
}

Web服务将数据保存为服务器上的文件:

byte[] byteUploadFile = Convert.FromBase64String(uploadData);
BinaryWriter binWriter = new         BinaryWriter(File.Open(Path.Combine(folderPath, fileName), FileMode.Create, FileAccess.ReadWrite));
binWriter.Write(byteUploadFile);
binWriter.Close();