Forge.JS AES加密然后解密文件会使编码混乱

时间:2018-10-02 14:49:00

标签: javascript encryption aes

我肯定做错了,但是我似乎找不到。我使用了两个不同的库,并且有完全相同的错误。请帮助我找出我的代码有什么问题。我做了一个最小的版本来演示我的案子:

index.html

<script src="lib/FileSaver.js"></script>
<script>
window.addEventListener('load', function() {
    document.getElementById("form_test").addEventListener('submit', function(e) {
        e.preventDefault();
        var worker = new Worker('worker.js');
        var file = document.getElementById("testfile").files[0];
        var key = document.getElementById("test_key").value;
        worker.postMessage({ op:'test', file:file, password:key, bits:256 });
        worker.onmessage = function(msg) {
            console.dir(msg);
            if (msg.data.progress == 'complete') {
                saveAs(new Blob([msg.data.plaintext.data]), file.name);
                // save decrypted file
            }
        }
    });
});
</script>

<h1>Test file upload</h1>
<form id="form_test">
    <input type="file" name="testfile" id="testfile" />
    <input type="text" name="test_key" id="test_key" />
    <input type="submit" />
</form>

worker.js

this.importScripts('./lib/forge.min.js');
this.importScripts('./helpers.js');

this.onmessage = function(msg) {
    switch (msg.data.op) {
        case 'test':
            console.dir(msg);
            var reader = new FileReaderSync();
            var file = reader.readAsText(msg.data.file, 'utf-8');
            var key = msg.data.password;
            var encryptedFile = encrypt(key, file);
            var clearFile = decrypt(key, encryptedFile);
            console.log(clearFile);
            this.postMessage({ progress: 'complete', plaintext: clearFile });
            break;
    }
};

helpers.js

function basename(str)
{
   var base = new String(str).substring(str.lastIndexOf('/') + 1); 
    if(base.lastIndexOf(".") != -1)       
        base = base.substring(0, base.lastIndexOf("."));
   return base;
}

String.prototype.getBytes = function() {
    var bytes = [];
    for (var i = 0; i < this.length; i++) {
        var charCode = this.charCodeAt(i);
        var cLen = Math.ceil(Math.log(charCode)/Math.log(256));
        for (var j = 0; j < cLen; j++) {
            bytes.push((charCode << (j*8)) & 0xFF);
        }
    }
    return bytes;
}

// ================================================================
// Utility function to generate the passwords in a canonical way.
// ================================================================
function make_password_bytes(password) {    
    var bytes = password.getBytes();

    // Round to the nearest power of 2 larger than the password size and
    // append bytes from the password. This allows us to regenerate it at
    // will from the original.
    var nearest_power_of_2 = Math.pow( 2, Math.ceil( Math.log( bytes.length ) / Math.log( 2 ) ) );
    if (bytes.length != nearest_power_of_2) {
        var remainder = nearest_power_of_2 - bytes.length;
        for(var i=0; i<remainder; i++) {
            var j = i % bytes.length;
            bytes.push(bytes[j]);
        }
    }
    return bytes;
}

// ================================================================
// Encrypt the data.
// ================================================================
function encrypt(password, data) {
    var key = make_password_bytes(password);
    var iv = forge.random.getBytesSync(16);
    var cipher = forge.cipher.createCipher('AES-CBC', key);

    cipher.start({iv: iv});
    cipher.update(forge.util.createBuffer(data));
    cipher.finish();

    var encrypted = cipher.output;
    var data = forge.util.bytesToHex(encrypted);
    var obj = {'iv': forge.util.bytesToHex(iv), 'encrypted': data};

    return JSON.stringify(obj); // String rep allows persistence.
}

// ================================================================
// Decrypt the data.
// ================================================================
function decrypt(password, encrypted) {
    var key = make_password_bytes(password);
    var obj = JSON.parse(encrypted);

    var iv = forge.util.createBuffer();
    var data = forge.util.createBuffer();
    iv.putBytes(forge.util.hexToBytes(obj.iv));
    data.putBytes(forge.util.hexToBytes(obj.encrypted));

    var decipher = forge.cipher.createDecipher('AES-CBC', key);
    decipher.start({iv: iv});
    decipher.update(data);
    decipher.finish();
    return decipher.output;
}

库:

FileSaver:https://raw.githubusercontent.com/eligrey/FileSaver.js/master/dist/FileSaver.js

伪造:https://cdn.jsdelivr.net/npm/node-forge@0.7.0/dist/forge.min.js

测试

  • 在测试表单中,我上传了一个文件。然后将该文件发送到Web Worker,在此处应对其进行加密,然后立即使用相同的加密密码(该密码派生给密钥,请参阅helpers.js第24行)立即解密。加密后解密的文件发送回主线程,并通过FileSaver.js下载该文件

问题

已加密然后解密的文件无法打开。而且奇怪的是,当我查看其hexdump时,它看起来很像原始的,但是有一些额外的字节:

$ hexdump -C file.png | head
00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|
00000010  00 00 01 15 00 00 01 52  08 06 00 00 00 dc b3 4b  |.......R.......K|
00000020  36 00 00 18 44 69 43 43  50 49 43 43 20 50 72 6f  |6...DiCCPICC Pro|
00000030  66 69 6c 65 00 00 58 85  95 59 05 58 94 cb d7 9f  |file..X..Y.X....|
00000040  77 93 85 5d ba bb bb 3b  a4 bb a4 1b 81 65 a9 a5  |w..]...;.....e..|
00000050  a5 41 10 09 51 e2 0a 16  2a a0 48 89 48 09 06 88  |.A..Q...*.H.H...|
00000060  88 80 84 28 82 84 80 60  00 0a 0a a2 62 a0 28 f5  |...(...`....b.(.|
00000070  bd 80 7a ef ff fe 9f e7  fb 9e 6f f6 99 f7 fd ed  |..z.......o.....|
00000080  99 33 67 ce 9c 33 73 66  ce 2e 00 1c 8a c4 f0 f0  |.3g..3sf........|
00000090  60 04 2d 00 21 a1 51 11  b6 c6 7a bc ce 2e ae bc  |`.-.!.Q...z.....|
$
$ hexdump -C file\ (1).png | head # <-- autorenamed because filename already existed
00000000  c3 bd 50 4e 47 0d 0a 1a  0a 00 00 00 0d 49 48 44  |..PNG........IHD|
00000010  52 00 00 01 15 00 00 01  52 08 06 00 00 07 33 4b  |R.......R.....3K|
00000020  36 00 00 18 44 69 43 43  50 49 43 43 20 50 72 6f  |6...DiCCPICC Pro|
00000030  66 69 6c 65 00 00 c2 a7  02 c3 bd 59 05 c2 a7 c3  |file.......Y....|
00000040  bd c3 b8 c3 9f c2 88 c3  bd c3 bd c2 a2 02 c3 bd  |................|
00000050  c3 bd c3 84 02 c3 bd c3  bd c3 a4 c3 bd 65 02 02  |.............e..|
00000060  c3 bd 41 10 09 c2 ae c3  bd 0a 16 c3 95 c3 bd c2  |..A.............|
00000070  b7 c3 bd 48 09 c3 b9 02  02 c3 bd c3 bd c3 97 02  |...H............|
00000080  c3 bd c3 bd 60 00 0a c3  b5 c3 bd c2 9d c3 bd c3  |....`...........|
00000090  97 02 02 c3 bd c2 85 02  02 c3 bd 02 02 02 c3 bd  |................|

如您所见,它确实很接近,几乎相似,我不明白为什么。

编辑:

我在worker.js第13行中添加了它:

console.dir({
    original: file,
    now: clearFile.data
});

它说:

Console log

似乎是编码问题...

0 个答案:

没有答案