Search code examples
scalaakka-streamakka-http

SHA256 of data stream


I am having a use case where i am downloading the file from URL using GET request. Is it possible to calculate SHA256 of file stream without saving to disk or holding an entire object in memory?


Solution

  • This can be accomplished with a MessageDigest and Sink.fold.

    First we need a function to create an empty digest and a function to update a digest with a 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
      }
    

    These two functions can then be used within a fold which is applied to the entity of an HttpResponse to update the digest with all ByteString values in the entity:

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