为什么表示encryption后解密文件的数据stream的行为与代表原始文件的数据stream的行为不同?

我创build了一个stream式传输video文件的HTTP服务器。

http.createServer((req, res) => { const file = 'example.mp4'; const size = fs.statSync(file).size; res.writeHead(200, { 'Content-Length': size, 'Content-Type': 'video/mp4' }); fs.createReadStream(file).pipe(res); }).listen(1911, '127.0.0.1'); 

我通过浏览器或video播放器连接到它,以validation它是否有效。 它确实。

我encryption一个文件:

 fs.createReadStream('example.mp4') .pipe(crypto.createCipher('aes-256-ctr', 'x')) .pipe(fs.createWriteStream('encrypted_file')); 

我解密它,并播放它来validation它的工作。 它确实。

然而,以下面的方式将解密和stream式传输组合在一起并没有默默无闻。

 const decrypt = crypto.createDecipher('aes-256-ctr', 'x'); http.createServer((req, res) => { const file = 'encrypted_file'; const size = fs.statSync(file).size; res.writeHead(200, { 'Content-Length': size, 'Content-Type': 'video/mp4' }); fs.createReadStream(file).pipe(decrypt).pipe(res); }).listen(1911, '127.0.0.1'); 

原始文件和encryption文件的字节大小相同,原始文件和encryption后解密文件的SHA-256哈希值相同。 鉴于此,我希望fs.createReadStream(original)fs.createReadStream(encrypted).pipe(decrypt)行为相同 – 但他们不。 没有video数据发送给用户,但是也不会向他们显示错误,并且错误事件也不会在http.Server实例上触发。

我错过了什么?

您的解密代码看起来不错,并在我的testing中正确的工作在我的变种短文件http://techslides.com/demos/sample-videos/small.mp4 (代码基于https://gist.github.com/paolorossi/ 1993068这是基于videostream与HTML 5通过node.js ):

 var http = require('http'), fs = require('fs'), util = require('util'), crypto = require('crypto'); http.createServer(function (req, res) { var path = 'encrypted'; var stat = fs.statSync(path); var total = stat.size; const decrypt = crypto.createDecipher('aes-256-ctr', 'x'); console.log('ALL: ' + total); res.writeHead(200, { 'Content-Length': total, 'Content-Type': 'video/mp4' }); fs.createReadStream(path).pipe(decrypt).pipe(res); }).listen(1912, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1912/'); 

您的文件可能会更大,所以打印到客户端的控制台请求可能很有用。 在我的testing中,未encryption和encryption的服务器都收到了两个请求,并发送了383631个字节。

我和你的变体之间的差异是:这是我的第一个node.js服务器(和第一个js程序之一),它不是第一次为你。 我不声明decrypt为全局常量,但作为本地常量。 通过debugging打印,我看到来自浏览器的两个请求; 第二个尝试修改您的变体的全局常量decrypt与错误:

 Server running at http://127.0.0.1:1912/ ALL: 383631 ALL: 383631 events.js:141 throw er; // Unhandled 'error' event ^ Error: write after end at writeAfterEnd (_stream_writable.js:159:12) at Decipher.Writable.write (_stream_writable.js:204:5) at ReadStream.ondata (_stream_readable.js:528:20) at emitOne (events.js:77:13) at ReadStream.emit (events.js:169:7) at readableAddChunk (_stream_readable.js:146:16) at ReadStream.Readable.push (_stream_readable.js:110:10) at onread (fs.js:1743:12) at FSReqWrap.wrapper [as oncomplete] (fs.js:576:17) 

所以移动decrypt在服务器代码 。 你的错误是重复使用的解码器对象不能重用( https://nodejs.org/api/crypto.html#crypto_class_decipher “一旦decipher.final()方法已被调用,解码器对象不能再用于解密数据。”); 并在第二次调用解码器可能会尝试解码具有错误(非零)计数器值的文件。