2017-07-24 2 views
2

Ich habe einen Anwendungsfall, wo ich die Datei von URL herunterladen mit GET-Anfrage. Ist es möglich, SHA256 des Dateistroms zu berechnen, ohne auf Festplatte zu speichern oder ein ganzes Objekt im Speicher zu halten?SHA256 von Datenstrom

Antwort

2

dies mit einem MessageDigest und Sink.fold erreicht werden kann.

Zuerst müssen wir eine Funktion eine leere verdauen und eine Funktion zum Erstellen einer Übersicht aktualisieren mit einem ByteBuffer:

import java.security.MessageDigest 
import java.nio.ByteBuffer 

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

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

Diese beiden Funktionen können dann innerhalb einer Falte verwendet werden, die auf die entity eines angewendet wird HttpResponse den Digest mit allen ByteString Werten in der Einheit aktualisieren:

import akka.http.scaladsl.model.HttpResponse 

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

gegebene Antwort erzeugt den falschen sha256 Wert. Wird berechnet, bevor der Stream abgeschlossen ist? Testcode: https://gist.github.com/rajeevprasanna/079813d9951da3016828b83f8fd09695 – Rajeev

+1

@Rajeev Ich modifizierte das 'runWith' zu einem' runFold'. Versuch das... –

1

Verwenden Sie eine der Methoden MessageDigest.getInstance("SHA-256").update.

Übergeben Sie Ihre Datei Stück für Stück.

nennen Dann digest()

Beispielcode:

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

Sie würden Flow benötigen, die man Daten auf einem anderen Daten verwandeln. In Ihrem Fall möchten Sie reinen Text in sha256-Text umwandeln.

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())} 

}