String ver- und entschlüsseln

Anfängerfragen zum Programmieren mit PureBasic.
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

String ver- und entschlüsseln

Beitrag von stevie1401 »

Ich suche verzweifelt nach einer Möglichkeit einen String zu verschlüsseln, aber auch nach einer Möglichkeit diesen wieder entschlüsseln zu können.
Bestimmt gibt es sowas hier im Forum schon, aber ich bin echt zu dusselig das zu finden.
Kann mir jemand helfen?
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: String ver- und entschlüsseln

Beitrag von Mijikai »

Hier ein Beispiel ver- und entschlüsselt (nutzt XOR, nur für Unicode):

Code: Alles auswählen

Procedure.s StringXOR(Text.s,Key.s)
  Protected *chr.Unicode
  Protected *key.Unicode
  If Text And Key
    *chr = @Text
    *key = @Key
    Repeat
      *chr\u ! *key\u
      *key + 2
      If *key\u = #Null
        *key = @Key
      EndIf
      *chr + 2
    Until *chr\u = #Null  
    ProcedureReturn Text
  EndIf
  ProcedureReturn #Null$
EndProcedure
Zuletzt geändert von Mijikai am 20.09.2021 22:27, insgesamt 1-mal geändert.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: String ver- und entschlüsseln

Beitrag von STARGÅTE »

@Mijikai: Ähm, scheint irgendwie nicht zu funktionieren, da kommt nur Müll raus:

Code: Alles auswählen

Debug StringXOR(StringXOR("Hallo Welt!", "123"), "123")
@stevie1401: Wie möchtest du denn Verschlüsseln? Soll die Länge des verschlüsselten Strings gleich der Länge des Original sein?
Soll der verschlüsselte String lesbar/darstellbar sein? Soll es kryptografisch sicher sein?
Gibt ja viele Möglichkeiten der Verschlüsselung.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: String ver- und entschlüsseln

Beitrag von NicTheQuick »

So geht das leider nicht. Sobald im Passwort ein Buchstabe mit dem Originaltext übereinstimmt, entsteht ein Nullbyte und man hat den Salat:

Code: Alles auswählen

Debug StringXOR(StringXOR("Hallo Welt!", "1a3"), "1a3")
Außerdem ist das natürlich nicht verschlüsselt im modernen Sinne. Dafür macht man erst mal einen Hash vom Passwort und nutzt dann AES oder vergleichbar gutes.
Bild
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: String ver- und entschlüsseln

Beitrag von stevie1401 »

Es geht nur darum Strings verschlüsselt auf die Festplatte speichern zu können, sodass nicht jeder gleicht den Text lesen kann.
Aber natürlich muss ich auch in der Lage sein, den Text dann wieder laden und entschlüsseln zu können.
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: String ver- und entschlüsseln

Beitrag von stevie1401 »

Ich denke, ich habe es selber hingekommen:

Code: Alles auswählen



UseSHA3Fingerprint()


Declare.s Verschluesseln(Text.s, Passwort.s)
Declare.s Entschluesseln(Text.s, Passwort.s)


Global.s Text
Global.s Passwort
Global.s s

Text = "Dies ist der Text üöäß^123§ℓ«»„“"
Passwort = "Passwort"

s = Verschluesseln(Text, Passwort)
Debug "Verschlüsselt: " + s
s = Entschluesseln(s, Passwort)
Debug "Entschlüsselt: " + s
Debug "Originaltext:  " + Text
If s <> Text
  Debug "Abweichung!"
EndIf


Procedure.s Verschluesseln(Text.s, Passwort.s)
  
  ; Der Text muss mindestens 16 Zeichen lang sein
  While Len(Text) < 16
    Text + " "
  Wend
  
  Protected n, i
  Protected *Input
  Protected *Output
  Protected *AESKey
  Protected *AESInitializationVector
    
  ; Der Schlüssel für AES wird aus dem Passwort generiert, per SHA3 
  Passwort = StringFingerprint(Passwort, #PB_Cipher_SHA3, 256)
  
  ; Passwort besteht aus 64 Hexadezimalzeichen (256 Bit).
  ; Die ersten 32 Zeichen werden der AESkey, die zweiten 32 Zeichen der AESInitializationVector.
  *AESkey = AllocateMemory(64)
  *AESInitializationVector = AllocateMemory(64)
  PokeS(*AESKey, Passwort, 32, #PB_String_NoZero)
  PokeS(*AESInitializationVector, Mid(Passwort, 32), 32, #PB_String_NoZero)
  
  *Input = UTF8(Text)
  n = MemorySize(*Input)
  
  *Output = AllocateMemory(n+16) ; Die Größe muss mindestens ein Vielfaches von 16 sein
     
  AESEncoder(*Input, *Output, n, *AESKey, 256, *AESInitializationVector)
  
  Text = Base64Encoder(*output, n)
  
  FreeMemory(*Input)
  FreeMemory(*Output)
  FreeMemory(*AESKey)
  FreeMemory(*AESInitializationVector)
  
  ProcedureReturn Text
EndProcedure
    
    
Procedure.s Entschluesseln(Text.s, Passwort.s)
  
  Protected n, i
  Protected *Input
  Protected *Output
  Protected *AESKey
  Protected *AESInitializationVector
    
  ; Der Schlüssel für AES wird aus dem Passwort generiert, per SHA3 
  Passwort = StringFingerprint(Passwort, #PB_Cipher_SHA3, 256)
  
  ; Passwort besteht aus 64 Hexadezimalzeichen (256 Bit).
  ; Die ersten 32 Zeichen werden der AESkey, die zweiten 32 Zeichen der AESInitializationVector.
  *AESkey = AllocateMemory(64)
  *AESInitializationVector = AllocateMemory(64)
  PokeS(*AESKey, Passwort, 32, #PB_String_NoZero)
  PokeS(*AESInitializationVector, Mid(Passwort, 32), 32, #PB_String_NoZero)
  
  n = Len(Text) * 3 / 4
  If Right(Text, 1) = "="
    n - 1
  EndIf
  If Right(text, 2) = "=="
    n - 1
  EndIf
  *Input = AllocateMemory(n)
  Base64Decoder(Text, *Input, n)
  
  *Output = AllocateMemory(n)
     
  If AESDecoder(*Input, *Output, n, *AESKey, 256, *AESInitializationVector) = 0
    Debug "Fehler beim Decodieren"
    ProcedureReturn
  EndIf
  Text = PeekS(*Output, -1, #PB_UTF8)

  FreeMemory(*Input)
  FreeMemory(*Output)
  FreeMemory(*AESKey)
  FreeMemory(*AESInitializationVector)
  
  ProcedureReturn text
EndProcedure

Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: String ver- und entschlüsseln

Beitrag von NicTheQuick »

Normalerweise leitet man den Initialisierungsvektor nicht von dem Passwort ab, sondern erzeugt kryptografisch sicher einen Zufallswert, den man dem verschlüsselten Ergebnis voranstellt. Deine Variante geht natürlich trotzdem und sollte sicher genug sein, es ist trotzdem anders gedacht.
Viel schlimmer ist das hier: Der StringFingerprint() sollte nicht einfach so als Hex-String benutzt werden, sondern zunächst in einen Binärwert umgewandelt und dann benutzt werden. PB-Strings sind nämlich Unicode, d.h. jedes zweite Byte ist 0. Und da es zusätzlich noch ein Hexstring ist, verschwendest du sogar 12 Bit aus insgesamt 16 Bit pro Zeichen, die immer 0 sind. Deine Entropie ist also nicht mehr so hoch wie sie sein sollte.
Bild
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: String ver- und entschlüsseln

Beitrag von stevie1401 »

Aha!
So besser?

Code: Alles auswählen




UseSHA3Fingerprint()


Declare.s Verschluesseln(Text.s, Passwort.s)
Declare.s Entschluesseln(Text.s, Passwort.s)


Global.s Passwort
Passwort = "Passwort"


NewList Text.s()

AddElement(Text())
Text() = "Kurz"
AddElement(Text())
Text() = "Mittellanger Text, der getestet wird."
AddElement(Text())
Text() = "Dies ist ein ganz ganz ganz langer Text 1234567890. Dies ist ein ganz ganz ganz langer Text 1234567890. Dies ist ein ganz ganz ganz langer Text 1234567890. Dies ist ein ganz ganz ganz langer Text 1234567890. Dies ist ein ganz ganz ganz langer Text 1234567890. Dies ist ein ganz ganz ganz langer Text 1234567890. Dies ist ein ganz ganz ganz langer Text 1234567890."
AddElement(Text())
Text() = "Dies ist der Text mit Sonderzeichen üöäß^123§ℓ«»„“"

Global.s s
ForEach Text()
  s = Verschluesseln(Text(), Passwort)
  Debug "Verschlüsselt: " + s
  s = Entschluesseln(s, Passwort)
  Debug "Entschlüsselt: |" + s + "|"
  Debug "Originaltext:  |" + Text() + "|"
  If s <> Text()
    Debug "Abweichung!"
  EndIf
Next Text()


Procedure.s Verschluesseln(Text.s, Passwort.s)
  
  ; Der Text muss mindestens 16 Zeichen lang sein, gegebenenfalls wird er mit Leerzeichen aufgefüllt.
  If Len(Text) < 16
    Text = LSet(Text, 16)
  EndIf
  
  Protected n, i
  Protected *Input
  Protected *Output
  Protected *AESKey
  Protected *AESInitializationVector
    
  ; Der Schlüssel für AES (*AESKey) wird aus dem Passwort generiert, per SHA3 (256 Bit)
  Passwort = StringFingerprint(Passwort, #PB_Cipher_SHA3, 256)
  *AESkey = AllocateMemory(32)
  For i = 0 To 31
    PokeB(*AESKey + i, Val("$" + Mid(passwort, 2 * i, 2)))
  Next i
  
  ; Der Initialisierungsvektor wird zufällig belegt und später dem verschlüsselten Text vorgestellt
  *AESInitializationVector = AllocateMemory(32)
  RandomData(*AESInitializationVector, 32)
  
  *Input = UTF8(Text)
  n = MemorySize(*Input)
  
  *Output = AllocateMemory(n+16) ; Die Größe muss mindestens ein Vielfaches von 16 sein
     
  AESEncoder(*Input, *Output, n, *AESKey, 256, *AESInitializationVector)
  
  Text = Base64Encoder(*AESInitializationVector, 32) + ":" + Base64Encoder(*output, n)
  
  FreeMemory(*Input)
  FreeMemory(*Output)
  FreeMemory(*AESKey)
  FreeMemory(*AESInitializationVector)
  
  ProcedureReturn Text
EndProcedure
    
    
Procedure.s Entschluesseln(Text.s, Passwort.s)
  
  Protected n, i
  Protected *Input
  Protected *Output
  Protected *AESKey
  Protected *AESInitializationVector
    
  ; Der Schlüssel für AES wird aus dem Passwort generiert, per SHA3 
  Passwort = StringFingerprint(Passwort, #PB_Cipher_SHA3, 256)
  *AESkey = AllocateMemory(32)
  For i = 0 To 31
    PokeB(*AESKey + i, Val("$" + Mid(passwort, 2 * i, 2)))
  Next i
  
  ; Der Initialisierungsvector steht am Anfang vom Text im Hexadezimalform
  *AESInitializationVector = AllocateMemory(32)
  Base64Decoder(Text, *AESInitializationVector, 32)
  
  ; Den vorderen Teil mit dem Initialisierungsvektor abschneiden
  Text = Mid(Text, 32 * 4 / 3 + 4)
  ; Die Länge des resultierenden Textes ermitteln
  n = Len(Text) * 3 / 4
  If Right(Text, 1) = "="
    n - 1
  EndIf
  If Right(text, 2) = "=="
    n - 1
  EndIf
  
  *Input = AllocateMemory(n)
  Base64Decoder(Text, *Input, n)
  
  *Output = AllocateMemory(n)   
  If AESDecoder(*Input, *Output, n, *AESKey, 256, *AESInitializationVector) = 0
    Debug "Fehler beim Decodieren"
    ProcedureReturn
  EndIf
  Text = PeekS(*Output, -1, #PB_UTF8)

  FreeMemory(*Input)
  FreeMemory(*Output)
  FreeMemory(*AESKey)
  FreeMemory(*AESInitializationVector)
  
  ProcedureReturn Text
EndProcedure

Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Antworten