数据流的SHA256

SHA256 of data stream

我有一个用例,我使用 GET 请求从 URL 下载文件。是否可以在不保存到磁盘或将整个对象保存在内存中的情况下计算文件流的 SHA256?

使用 MessageDigest.getInstance("SHA-256").update 方法之一。

将您的文件逐个传递给它。

然后调用digest()

示例代码:

    MessageDigest instance = MessageDigest.getInstance("SHA-256");
    for(byte[] arr: source){
        instance.update(arr);
    }
    byte[] result = instance.digest();

这可以通过 MessageDigest and Sink.fold 来完成。

首先我们需要一个函数来创建一个空的摘要和一个用 ByteBuffer:

更新摘要的函数
import java.security.MessageDigest
import java.nio.ByteBuffer

def emptySHA256Digest : MessageDigest = MessageDigest getInstance "SHA-256" 

val updateDigest : (MessageDigest, ByteBuffer) => MessageDigest = 
  (messageDigest, byteBuffer) => {
    messageDigest update byteBuffer
    messageDigest
  }

然后可以在应用于 HttpResponseentity 的折叠中使用这两个函数,以使用实体中的所有 ByteString 值更新摘要:

import akka.http.scaladsl.model.HttpResponse

val responseBodyToDigest : HttpResponse => Future[MessageDigest] = 
  (_ : HttpResponse)
    .entity
    .dataBytes
    .map(_.asByteBuffer)
    .runFold(emptySHA256Digest)(updateDigest)

您需要 Flow,它将一个数据转换为另一个数据。在您的情况下,您想将纯文本转换为 sha256 文本。

def digest(algorithm: String = "SHA-256"): Flow[ByteString, ByteString, NotUsed] = {
    Flow[ByteString].fold(MessageDigest.getInstance(algorithm)) {
        case (digest: MessageDigest, bytes:ByteString) => {digest.update(bytes.asByteBuffer); digest}}
          .map {case md: MessageDigest => ByteString(md.digest())}
}