Byte Array ohne Verluste in String konvertieren

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Byte Array ohne Verluste in String konvertieren

    Hallo Liebe Community,

    Also, ich muss einige Daten Verschlüsseln,
    diese Ausgeben und nach späterer Eingabe dann wieder Entschlüsseln.

    Vorgabe ist AES-256.

    Ich verschlüssele also einen String, dabei kommt ein Byte[] heraus.
    Diesen Byte[] konvertiere ich in einen Base64-String zur Ausgabe, wobei ich Base64 vom Vorgabe Projekt beibehalten muss.

    Zum entschlüsseln also dann Base64-String in Byte[] konvertieren und Entschlüsseln.

    Problem:
    Ich erhalte beim entschlüsseln eine System.Security.Cryptography.CryptographicException: "Die Eingabedaten sind kein vollständiger Block."

    Daten wie Key, IV und Salt sind identisch, habe ich extra überprüft.

    Verschlüsselung:

    VB.NET-Quellcode

    1. [code]
    2. Dim aescrypto As Aes = Aes.Create()
    3. Dim pdb As New Rfc2898DeriveBytes(key, salt)
    4. aescrypto.Key = pdb.GetBytes(32)
    5. aescrypto.IV = pdb.GetBytes(16)
    6. Dim ms As New MemoryStream()
    7. Dim cs As New CryptoStream(ms, aescrypto.CreateEncryptor(), CryptoStreamMode.Write)
    8. cs.Write(Encoding.Unicode.GetBytes(plaintext), 0, Encoding.Unicode.GetBytes(plain).Length)
    9. cs.FlushFinalBlock()
    10. cs.Close()
    11. Return Convert.ToBase64String(ms.ToArray())


    Entschlüsselung:

    VB.NET-Quellcode

    1. [code]
    2. Dim m_aesCrypto As Aes = Aes.Create()
    3. Dim pdb As New Rfc2898DeriveBytes(key, salt)
    4. m_aesCrypto.Key = pdb.GetBytes(32)
    5. m_aesCrypto.IV = pdb.GetBytes(16)
    6. Dim ms As New MemoryStream()
    7. Dim cs As New CryptoStream(ms, m_aesCrypto.CreateDecryptor(), CryptoStreamMode.Write)
    8. cs.Write(cipher, 0, cipher.Length)
    9. cs.FlushFinalBlock()
    10. cs.Close()
    11. Return Encoding.Unicode.GetString(ms.ToArray())


    Exception tritt bei cs.FluschFinalBlock() auf.

    Meiner Vermutung liegt das Problem dabei, dass beim Konvertieren des Byte[] in einen String Zeichen oder Daten verloren gehen.
    Aber wie kann ich den Byte[] sonst Ausgeben, ohne Ihn in einen String konvertieren zu müssen,
    bzw. wie kann ich ihn so konvertieren, dass ich ihn auch wieder entschlüsseln kann?

    Ich hoffe Ihr könnt mir helfen und dass ich alle Forum-Regeln beachtet habe. :D

    Viele Grüße

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „mct“ ()

    ich hab vor längerem mal eine Lösung gecodet - ist in den Tipps - aber jetzt konkret nicht alles auf Lager.
    Eigentümlich kommt mir vor, dass bei dir sowohl beim encrypten als auch beim decrypten der cryptoMode.Write auftaucht - müsste nicht auch mal cryptoMode.Read verwendet wern?
    @mct
    Allgemeines:
    Bitte verwende den entsprechenden VB.Net-Codetag:
    Bugs (Fehler) im Forum bitte hier melden (WBB4 - neu)
    Verwende Using für Streams, sofern das möglich ist:
    Was sind verwaltete / nicht verwaltete Ressourcen
    Dadurch werden die Streams automatisch geschlossen und geflusht. Das stellt sicher, dass alle Daten vollständig verarbeitet sind.

    Zum Problem:
    Teste die einzelnen Schritte.
    Nimm ein Byte-Array, fülle es mit gut lesbaren Daten (z.B. 1, 2, 3, 4, ...}, wandle es in einen Base64-String um, speichere diesen so, wie Du im Moment die verschlüsselten Daten speicherst, lies ihn wieder aus, zurückkonvertieren und schauen, ob wieder das gleiche herauskommt.

    Wenn das passt, teste die Verschlüsselung, ohne zu Base64 zu konvertieren und ohne zu speichern.


    @ErfinderDesRades
    Der CryptoStreamMode gibt nur an, ob in den CryptoStream mit Stream.Write geschrieben wird (Daten werden in den gekapselten Stream (hier den MemoryStream) geschrieben), oder ob aus ihm mit Stream.Read gelesen wird (das wäre dann, die Daten aus dem gekapselten Stream zu lesen).
    Man kann auch sowas basteln:

    VB.NET-Quellcode

    1. Using BottomLevelStream As New MemoryStream(...)
    2. Using DecryptionStream As New CryptoStream(BottomLevelStream, Decryptor, CryptoStreamMode.Write)
    3. Using EncryptionStream As New CryptoStream(DecryptionStream, Encryptor, CryptoStreamMode.Write)
    4. EncryptionStream.Write(... )
    5. End Using
    6. End Using
    7. End Using

    Und theoretisch müsste im BottomLevelStream das gleiche herauskommen, wie man in den EncryptionStream hineingeschrieben hat.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Es hat jetzt geklappt.
    Wie sich herausgestellt hat war der eigentliche Grund garnicht die Entschlüsselung,
    sondern die komische Art des Original Projekts, die Daten zu zerstückeln und dann zu Verschlüsseln.

    Danke für eure Hilfe und Danke Niko, durch deine Antwort hab ich die Funktionen nochmal mit "lesbaren" Daten gefüttert
    und bin drauf gekommen :thumbsup: :thumbsup:
    genau, das "Verschlüsseln und Autentifizieren"-Tut.
    Ja, ist doch komisch: Dort verwende ich zum Schreiben verschlüsselter Daten cryptoMode.Write, und zum Lesen verschlüsselter Daten cryptoMode.Read.
    Deshalb wundert mich das, dass dieser Mode jetzt gar keinen Unterschied machen soll.
    @ErfinderDesRades
    Nö, der gibt nur die Richtung an, in die der Stream arbeitet. Gibt ja sonst keine Möglichkeit, das zu ändern.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    jo, ich glaub, langsam dämmerts.
    Bei mir lese ich das Verschlüsselte aus einem Stream, um zu entschlüsseln.
    Hier aber wird das Verschlüsselte **auch** reingeschrieben.
    Das funzt - kommt mir aber verdächtig vor, irgendwie unperformant.

    Verschlüsseltes muss man doch **lesen**, nicht schreiben.

    Ja, glaub das ergibt sich aus der Unart, dass beim Verschlüsseln kein Stream entsteht, sondern der wird umgewurstelt in ein Byte-Array, und das wiederum in einen (Base64-)String.
    Aus dem String kann ein CryptoStream dann nicht mehr lesen, weil ein String ist ja kein Stream (mehr). Deshalb muss man den erst zurückwursteln in ein Byte-Array, und das Byte-Array dann in den Crypt-Stream schreiben.
    Raus kommt ein MemoryStream, und den muss man nochmal umwursteln, das endlich ein lesbarer String bei rauskommt.

    Also ich täte empfehlen: Den Klartext mit einem StreamWriter in den CryptoStream schreiben, und was rauskommt - sei es ein MemoryStream oder ein FileStream - so lassen. Kein Byte-Array und keinen (Base64)String draus machen, den ja doch keiner lesen kann.
    Belässt man den verschlüsselten Stream als Stream, dann kann man beim Entschlüsseln auch direkt draus lesen, mit cryptoMode.Read
    Nach dem Schema wäre es eigentlich gedacht. Aber für den Fall, dass man's mal andersrum braucht, ist es doch praktisch zu haben.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils