md5以递增方式散列大文件?

时间:2015-05-22 17:19:50

标签: javascript hash md5 cryptography

在浏览器中,我使用JS FileReader()读取文件.readAsBinaryString()。使用CryptoJS库我可以MD5哈希数据。

这很好但我不知道如何处理大文件。例如。只是读取2GiB文件会导致浏览器窗口崩溃。我可以从文件数据切片blob并在我去的时候哈希,但这不会阻止其他人在不遵循与我相同的步骤的情况下验证相同的哈希值吗?

在这种情况下,有没有办法获取大文件的md5哈希值?例如,你如何计算1TB文件的md5哈希值?我是否需要以流形式读取文件?

第一次在这个上切牙,我不知道该怎么做。

这存在于一个角度指令中,因此也就是范围。

var reader = new FileReader();
                reader.onload = function (loadEvent) {
                    scope.$apply(function () {
                        scope.files = changeEvent.target.files;
                        scope.fileread = loadEvent.target.result;
                        scope.md5Data = CryptoJS.MD5(scope.fileread).toString();
                    });
                }
                // First ten megs of the file
                reader.readAsBinaryString((changeEvent.target.files[0]).slice(0, 10 * 1024 * 1024));

5 个答案:

答案 0 :(得分:2)

使用spark-md5Q

由于其他答案都没有提供完整的代码段,因此您将如何计算大型文件的 MD5哈希



function calculateMD5Hash(file, bufferSize) {
  var def = Q.defer();

  var fileReader = new FileReader();
  var fileSlicer = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
  var hashAlgorithm = new SparkMD5();
  var totalParts = Math.ceil(file.size / bufferSize);
  var currentPart = 0;
  var startTime = new Date().getTime();

  fileReader.onload = function(e) {
    currentPart += 1;

    def.notify({
      currentPart: currentPart,
      totalParts: totalParts
    });

    var buffer = e.target.result;
    hashAlgorithm.appendBinary(buffer);

    if (currentPart < totalParts) {
      processNextPart();
      return;
    }

    def.resolve({
      hashResult: hashAlgorithm.end(),
      duration: new Date().getTime() - startTime
    });
  };

  fileReader.onerror = function(e) {
    def.reject(e);
  };

  function processNextPart() {
    var start = currentPart * bufferSize;
    var end = Math.min(start + bufferSize, file.size);
    fileReader.readAsBinaryString(fileSlicer.call(file, start, end));
  }

  processNextPart();
  return def.promise;
}

function calculate() {

  var input = document.getElementById('file');
  if (!input.files.length) {
    return;
  }

  var file = input.files[0];
  var bufferSize = Math.pow(1024, 2) * 10; // 10MB

  calculateMD5Hash(file, bufferSize).then(
    function(result) {
      // Success
      console.log(result);
    },
    function(err) {
      // There was an error,
    },
    function(progress) {
      // We get notified of the progress as it is executed
      console.log(progress.currentPart, 'of', progress.totalParts, 'Total bytes:', progress.currentPart * bufferSize, 'of', progress.totalParts * bufferSize);
    });
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/q.js/1.4.1/q.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/2.0.2/spark-md5.min.js"></script>


<div>
  <input type="file" id="file"/>
  <input type="button" onclick="calculate();" value="Calculate" class="btn primary" />
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

  

我可以从文件数据中切割blob并在我去的时候散列,但这不会阻止其他人在不遵循与我相同的步骤的情况下验证相同的散列吗?

是的,因此这正是MD5算法在合同中提供的内容:

  1. 你有一个文件
  2. 通过添加单个“1”和多个“0”来填充文件,因此文件可以被512分割。
  3. 每个回合计算一个512字节文件的md5哈希值,并将其与之前的结果相结合。
  4. 因此,您无需重复这些步骤,并确保其他用户也这样做。

    由于MD5是以块为单位计算的,因此您可以在此处阅读(尽管使用了nodejs的crypt模块,它是googlecode项目crypto-js的模块化端口)。

    http://www.hacksparrow.com/how-to-generate-md5-sha1-sha512-sha256-checksum-hashes-in-node-js.html

答案 2 :(得分:1)

您可能需要检查CryptoJS网站上的progressive hashing段。

示例:

var sha256 = CryptoJS.algo.SHA256.create();
sha256.update("Message Part 1");
sha256.update("Message Part 2");
sha256.update("Message Part 3");
var hash = sha256.finalize();

SHA256替换为MD5和presto(同时重命名变量,我会让你选择一个好名字)。

答案 3 :(得分:1)

使用 SparkMD5 https://github.com/satazor/SparkMD5

var spark = new SparkMD5(); 
spark.append('Hi');
spark.append('there');
var hexHash = spark.end();

它有一个文件切片示例

答案 4 :(得分:0)

用法:

pyramid_tm

from myapp.models import get_tm_session tmp_tm = transaction.TransactionManager(explicit=True) with tmp_tm: dbsession_factory = request.registry['dbsession_factory'] tmp_dbsession = get_tm_session(dbsession_factory, tmp_tm) # ... do stuff with tmp_dbsession that is committed in this with-statement ride = appstruct_to_ride(tmp_dbsession, appstruct) # do not use this ride object outside of the with-statement tmp_dbsession.add(ride) tmp_dbsession.flush() ride_id = ride.id # we are now committed so go ahead and start your background worker update_weather_task = update_ride_weather.delay(ride_id) # maybe you want the ride object outside of the tmp_dbsession ride = dbsession.query(Ride).filter(Ride.id==ride_id).one() return {...} 来源:

const md5 = await incrementalMD5(file)