Javascript formdata:在附加之前加密文件

Javascript formdata: encrypt files before appending

我需要修改涉及将文件上传到服务器的现有前端 (angular) 代码。现在文件在上传前需要加密。

当前方法使用 FormData 附加多个文件并在单个请求中发送它们,如下所示:

    function uploadFiles(wrappers){

        var data = new FormData();

        // Add each file
        for(var i = 0; i < wrappers.length; i++){

            var wrapper = wrappers[i];
            var file = wrapper.file;
            data.append('file_' + i, file);
        }

        $http.post(uri, data, requestCfg).then(

        /*...*

我一直在其他项目中使用 Forge,但从来没有在这种情况下使用过,也没有真正了解如何动态加密文件并将它们附加为 FormData 内容。

Forge 提供了一个简单的 API:

var key = forge.random.getBytesSync(16);
var iv = forge.random.getBytesSync(8);

// encrypt some bytes
var cipher = forge.rc2.createEncryptionCipher(key);
cipher.start(iv);
cipher.update(forge.util.createBuffer(someBytes));
cipher.finish();
var encrypted = cipher.output;

后端使用 Formidable 接收文件,所有文件处理都已连线。因此,我想坚持使用现有的前端逻辑,而只是插入加密逻辑。在那里,不是必须加密整个表单数据...我还没有找到解决这个问题的好办法。

非常欢迎提出建议!

好的,找到解决方案并添加解密代码。这增加了一层异步代码。

        function appendFile(aFile, idx){

            // Encrypt if a key was provided for this protocol test
            if(!key){
                data.append('dicomfile_' + idx, file);
                appendedCount++;
                onFileAppended();
            }

            else{
                var reader = new FileReader();
                reader.onload = function(){

                    // 1. Read bytes
                    var arrayBuffer = reader.result;
                    var bytes = new Uint8Array(arrayBuffer);    // byte array aka uint8

                    // 2. Encrypt
                    var cipher = forge.cipher.createCipher('AES-CBC', key);
                    cipher.start({iv: iv});
                    cipher.update(forge.util.createBuffer(bytes));
                    cipher.finish();

                    // 3. To blob (file extends blob)
                    var encryptedByteCharacters = cipher.output.getBytes();     // encryptedByteCharacters is similar to an ATOB(b64) output
                    // var asB64 = forge.util.encode64(encryptedBytes); 
                    // var encryptedByteCharacters = atob(asB64);

                    // Convert to Blob object
                    var blob = byteCharsToBlob(encryptedByteCharacters, "application/octet-stream", 512);

                    // 4. Append blob
                    data.append('dicomfile_' + idx, blob, file.name);

                    // Decrypt for the sake of testing
                    if(true){

                        var fileReader = new FileReader();
                        fileReader.onload = function() {
                            arrayBuffer = this.result;
                            var bytez = new Uint8Array(arrayBuffer);
                            var decipher = forge.cipher.createDecipher('AES-CBC', key);
                            decipher.start({iv: iv});
                            decipher.update(forge.util.createBuffer(bytez));
                            decipher.finish();
                            var decryptedByteCharacters = decipher.output.getBytes();
                            var truz = bytes === decryptedByteCharacters;
                            var blob = byteCharsToBlob(decryptedByteCharacters, "application/octet-stream", 512);
                            data.append('decrypted_' + idx, blob, file.name + '.decrypted');

                            appendedCount++;
                            onFileAppended();       
                        };
                        fileReader.readAsArrayBuffer(blob);
                    }

                    else{

                        // z. Resume processing
                        appendedCount++;
                        onFileAppended();                           
                    }
                }

                // Read file
                reader.readAsArrayBuffer(aFile);
            }
        }

function onFileAppended(){

            // Only proceed when all files were appended and optionally encrypted (async) 
            if(appendedCount !== wrappers.length) return;
            /* resume processing, upload or do whathever */