String mit _Crypt_EncryptData() verschlüsseln

  • Hallo zusammen

    Bin langsam echt am verzweifeln und finde den Fehler nicht. Eigentlich müsste mein Script doch "0xA338D5F9" ausgeben. Es gibt aber "£8Õù" aus. Hat jemand ne Ahnung, wo der Fehler liegen?

    Code
    #include <Crypt.au3>
    $g_hKey = _Crypt_DeriveKey(StringToBinary("CryptPassword"), $CALG_RC4)
    $sRead = "Test"
    $dEncrypted = _Crypt_EncryptData($sRead, $g_hKey, $CALG_USERKEY)
    ConsoleWrite($dEncrypted)
  • Hat jemand ne Ahnung, wo der Fehler liegt?

    Verwende mal eine MsgBox zur Ausgabe, nicht ConsoleWrite :

    AutoIt
    #include <Crypt.au3>
    Local $g_hKey = _Crypt_DeriveKey("CryptPassword", $CALG_RC4)
    $sRead = "Test"
    $dEncrypted = _Crypt_EncryptData($sRead, $g_hKey, $CALG_USERKEY)
    MsgBox(0, "", $dEncrypted)

    EDIT : Sidewinder :

    Wenn ich ConsoleWrite mit & @CRLF abschließe klappt es.

    AutoIt
    #include <Crypt.au3>
    $g_hKey = _Crypt_DeriveKey(StringToBinary("CryptPassword"), $CALG_RC4)
    $sRead = "Test"
    $dEncrypted = _Crypt_EncryptData($sRead, $g_hKey, $CALG_USERKEY)
    ConsoleWrite($dEncrypted & @CRLF)

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    Einmal editiert, zuletzt von Musashi (27. April 2022 um 09:50)

  • Musashi

    Vielen Dank für Deinen Input. Insbesondere der Edit hat geholfen, das eigentliche Script zum Laufen zu bringen. Dieses soll im LDAP ein Passwort verschlüsselt in ein ExtensionAttribute des jeweiligen Benutzers schreiben. Mit "& @CRLF" wird der Wert dann korrekt ins Attribut geschrieben, aber im 2. Schritt dann nicht mehr korrekt entschlüsselt.

    Ich verwende jetzt & "".

    Sollte mir irgendwer erklären können, was der Sinn dahinter ist, wäre das klasse. Ich erkenne ihn irgendwie nicht. Insbesondere, da das weder im Beispiel-Script noch in anderen von mir erstellen nötig war.

  • Sidewinder Ich habe bei mir immer ein BinaryToString() drum herum, also so (um bei deinem Beispiel zu bleiben):

    AutoIt
    #include <Crypt.au3>
    $g_hKey = _Crypt_DeriveKey(StringToBinary("CryptPassword"), $CALG_RC4); Hier machst du das Gleiche ja auch andersherum, was meine Vermutung bestätigt.
    $sRead = "Test"
    $dEncrypted = BinaryToString(_Crypt_EncryptData($sRead, $g_hKey, $CALG_USERKEY))
    ConsoleWrite($dEncrypted & @CRLF) ;@CRLF nur für Lesbarkeit in der Konsole, funktioniert auch ohne!

    Ich denke das Problem ist der Ausgabetyp, der durch ein einfügen eines Zeichens (egal ob ein leerer String oder Zeilenumbruch etc.) von Autoit dann implizit in einen String convertiert wird.

    3 Mal editiert, zuletzt von Moombas (27. April 2022 um 11:01) aus folgendem Grund: Kommentar eingefügt.

  • Eigentlich müsste mein Script doch "0xA338D5F9" ausgeben. Es gibt aber "£8Õù" aus.

    Zitat aus der Hilfe zu ConsoleWrite:

    Binary data is written as-is. It will not be converted to a string. To print the hex representation of binary data, use the String() function to explicitly cast the data to a string.

    Heißt: $dEncrypted ist ordentlich vom Typ Binary und kann auch entsprechend weiterverwendet werden.
    Wenn du per Consolewrite die Hex-Repräsentation hiervon darstellen willst musst du noch ein String() drumrum machen.

    Mit "& @CRLF" wird der Wert dann korrekt ins Attribut geschrieben, aber im 2. Schritt dann nicht mehr korrekt entschlüsselt.

    Was auch logisch ist, da du die Daten ja komplett veränderst durch die implizite Konvertierung in einen String.

    Denn was passiert? Durch das & @CRLF wird $bEncrypted per String() in dessen Hexadezimaldarstellung gewandelt und als String ausgegeben. Sprich: $bEncrypted wird implizit zu "0xA338D5F9" & @CRLF. Wichtig - das ist jetzt ein String und keine Hex-Repräsentation der eigentlichen binären Daten. Stattdessen hat dadurch $bEncrypted nun den Wert 0x307841333338443546390D0A

    Daher kommt natürlich beim decrypten etwas völlig anderes raus.

    Lass also den Spaß mit dem & CRLF und verwende die $bEncrypted einfach unangetastet weiter.

  • AspirinJunkie : Hatte ich das oben nicht bereits bei #4 erwähnt bezüglich des Datentyps?^^

    Wegen der Umwandlung oder nicht: Kommt ja darauf an wo/wie man das Ganze verwendet. Ich habe z.B. das mit einer Benutzereingabe und Prüfung verbunden und arbeite daher mit einem String.

    Daher habe ich mir folgende Funktion gebaut (für AES256):

    AutoIt
    Func Uncrypt($Crypt) ;Beispiel für entschlüsseln wäre natürlich auch zum verschlüsseln möglich
    Local Const $vCryptKey = _Crypt_DeriveKey(StringToBinary('DeinCryptKey'), $CALG_AES_256)
      Return BinaryToString(_Crypt_DecryptData('0x' & $Crypt, $vCryptKey, $CALG_USERKEY))
    EndFunc

    Hat auch ein wenig was davon wie man damit umgehen möchte.

  • Hatte ich das oben nicht bereits bei #4 erwähnt bezüglich des Datentyps?^^

    Du hast vermutet, dass das Problem darin liegen könnte durch die implizite Konvertierung in einen String, in deinem Code dann aber sein Grundproblem nicht gelöst.

    Das BinaryToString ändert grundsätzlich nichts an den Daten sondern markiert diese lediglich als String.
    Für die Weiterverarbeitung erst einmal unschädlich, da damit auch das Decrypten auch funktioniert (Die Daten bleiben ja gleich) aber sein Ausgabeproblem mit ConsoleWrite bleibt bestehen.

    Daher ist das BinaryToString hier ziemlich sinnfrei.

    Vielleicht zum Verständnis nochmal zusammengefasst:

    Man hat eine Binärvariable $bEncrypted. Deren Inhalt ist die Bitfolge 10100011001110001101010111111001

    BinaryToString() interpretiert diese Bitfolge als ANSI-kodierten Text -> "£8Õù" (Die Bitfolge bleibt gleich)

    String() gibt die Hexadezimaldarstellung der Bitfolge als String zurück -> "0xA338D5F9" (als ANSI kodiert ist der Inhalt der Variable nun 0x307841333338443546390D0A)

    Sidewinder

    Nochmal zusammengefasst:
    Lass $bEncrypted so wie es ist - also $dEncrypted = _Crypt_EncryptData($sRead, $g_hKey, $CALG_USERKEY) (ohne BinaryToString drumherum)

    Willst du dir den Inhalt von $bEncrypted als Hex-Repräsentation in ConsoleWrite oder anderswoe ausgeben lassen dann so: ConsoleWrite(String($dEncrypted))

    Wichtig!: Nur für Ausgabezwecke zu einem String konvertieren. Willst du stattdessen dennoch mit der Hexrepräsentation weiterarbeiten musst du dann nämlich vor dem Decrypten sonst das ganze via Binary() zurück wandeln.

    Einmal editiert, zuletzt von AspirinJunkie (27. April 2022 um 12:22)

  • Das BinaryToString ändert grundsätzlich nichts an den Daten sondern markiert diese lediglich als String.
    Für die Weiterverarbeitung erst einmal unschädlich, da damit auch das Decrypten auch funktioniert (Die Daten bleiben ja gleich) aber sein Ausgabeproblem mit ConsoleWrite bleibt bestehen.

    Daher ist das BinaryToString hier ziemlich sinnfrei.

    Bei mir funktioniert mit dem BinaryToString() die Konsolenausgabe einwandfrei ohne ein @CRLF oder so hinten dran, daher nicht Sinnfrei

  • Hmm, du hast Recht, irgendwas muss ich noch anders gemacht haben, ich schaue nochmal.

    So funktioniert es bei mir die Anzeige nach dem Entschlüsseln (bei mir gibt der Benutzer halt nur den Wert ohne den Hex-Indikator an, daher hier das explizite '0x' am Start):

    AutoIt
    Global Const $vCryptKey = _Crypt_DeriveKey(StringToBinary('CryptPassword'), $CALG_RC4)
    Global $Return = BinaryToString(_Crypt_DecryptData('0x' & 'A338D5F9', $vCryptKey, $CALG_USERKEY))
    ConsoleWrite($Return)

    Das Gleiche jedoch scheint bei der Verschlüsselung nicht zu funktionieren. Aber auch andersherum nicht. Daher ergibt sich:

    6 Mal editiert, zuletzt von Moombas (27. April 2022 um 15:51)

  • Daher ergibt sich:



    Global $Return = String(_Crypt_EncryptData($sRead, $vCryptKey, $CALG_USERKEY))

    Das ist genau das was ich vorhin versucht habe zu erklären: Warum wollt ihr unbedingt das Ergebnis von _Crypt_EncryptData als Hex-String IN der Variable haben?

    Das braucht man doch nur für die Ausgabe oder eventuell den Export.

    Es ist daher sinnvoller $Return das direkte Binary aus dem Return von _Crypt_EncryptData zu belassen.

    Und erst sobald man die Daten sich in Hexdarstellung anschauen will, dann entsprechend erst dort die Konvertierung durchzuführen: ConsoleWrite(String($Return))

    Denn: Man schleppt nur sinnfrei Overhead mit sich rum.

    In dem Beispiel ist $Return ohne String() 4 Byte groß und wächst durch dieses dann vermeidbar auf 10 Byte an.

    Performanceoverhead gibt es durch die expliziten wie auch impliziten Konvertierungen ebenso - sind jedoch aber vernachlässigbar.

    Bei größeren zu verschlüsselnden Daten wird es entsprechend mehr ohne einen (für mich) erkennbaren Vorteil zu haben.

    Sprich: Die Daten selbst von deren Darstellung trennen.

    Einmal editiert, zuletzt von AspirinJunkie (27. April 2022 um 20:55)

  • AspirinJunkie Es ging ja nur um die (Konsolen-)Ausgabe bei meinem Beispiel. (bzw. in meiner Anwendung bekomme ich halt einen String von der User-Eingabe und prüfe den dann nach der (De)kodierung direkt gegen). Ich wollte nur zeigen, was man mit dem Ergebnis machen muss, um damit (aus welchen Gründen auch immer) als String weiter arbeiten zu können. Ansonsten stimme ich dir zu 100% zu, wobei die Performance-Gründe, je nach Programm, zu relativieren sind.

    In wie weit Sidewinder hier wirklich die Ausgabe als String braucht oder einfach mit dem Original weiter machen kann (und das Consolewrite nur ein Versuch zur Kontrolle war), kann wohl nur er selber beurteilen, da wir den Rest des Codes und deren Anwendug nicht kennen.

  • So klappt es auch:

    ConsoleWrite($dEncrypted & '')

    Aber dann erfolgt die Umwandlung implizit. Ich bevorzuge dies immer explizit handzuhaben (Was das von AspirinJunkie angesprochene String() machen würde).

    Und das klappt auch nur beim Verschlüsseln, beim Entschlüsseln würdest du dann 0x54657374 erhalten anstatt wieder Test . Dort ist das BinaryToString() notwendig.

  • Ein Fehler liegt imho nur gedanklich vor. Zu erklärungszwecke. Das Anhägen von@Crlf bewirkt das gleiche wie Beispiel3 aus der Hilfe. Die Erklärung weshalb und wieso der Parser intern selbst die LangVersion erzeugt wei wohl nur Jos, ein Erklärungsversuch für Laien (und hoffentlich ohne zuviel Simultanübersetzern) von Andy ist vielen mit Sicherheit zu technisch kommt aber der Realität am nähsten.

    mfg (auto)Bert