Seite 1 von 1

AES Verschlüsselung für Strings

Verfasst: 27.08.2010 15:53
von Christian+
Da ich heute eine einfache Möglichkeit gesucht habe Strings mit AES zu verschlüsseln und entschlüsseln habe ich mir mal schnell zwei Funktionen dazu geschrieben die es so einfach wie möglich machen.

Code: Alles auswählen

EnableExplicit

Procedure.s StringEncoder( String$, Key$ )
  Protected Size.l, *Input, *IV, *Ciphered, *Base64, Ciphered$
  If String$
    Size = StringByteLength( String$ ) + SizeOf(Character)
    If Size < 16 : Size = 16 : EndIf
    *Input = AllocateMemory( Size )
    If *Input
      PokeS( *Input, String$ )
      Key$ = MD5Fingerprint( @Key$, StringByteLength( Key$ ) )
      *IV = AllocateMemory( 16 )
      CryptRandomData( *IV, 16 )
      *Ciphered = AllocateMemory( Size + 16 )
      If *Ciphered
        CopyMemory( *IV, *Ciphered, 16 )
        AESEncoder( *Input, *Ciphered + 16, Size, @Key$, 256, *IV, #PB_Cipher_CBC )
        *Base64 = AllocateMemory( Size * 1.35 + 64 )
        If *Base64
          Size = Base64Encoder( *Ciphered, Size + 16, *Base64, Size * 1.35 + 64 )
          Ciphered$ = PeekS( *Base64, Size, #PB_Ascii)
          FreeMemory( *Base64 )
        EndIf
        FreeMemory( *Ciphered )
      EndIf
      FreeMemory( *IV )
      FreeMemory( *Input )
    EndIf
  EndIf
  ProcedureReturn Ciphered$
EndProcedure

Procedure.s StringDecoder( String$, Key$ )
  Protected Size.l, *IV.l, *Deciphered, *Base64, Deciphered$, *Buffer
  If String$
    Size = StringByteLength(String$, #PB_Ascii) + SizeOf(Character)
    *Base64 = AllocateMemory( Size + 64 )
    If *Base64
      *Buffer = AllocateMemory(Size)
      PokeS(*Buffer, String$, StringByteLength(String$, #PB_Ascii), #PB_Ascii)
      Size = Base64Decoder( *Buffer, StringByteLength(String$, #PB_Ascii), *Base64, Size + 64 )
      Key$ = MD5Fingerprint( @Key$, StringByteLength( Key$ ) )
      *IV = AllocateMemory( 16 )
      CopyMemory( *Base64, *IV, 16 )
      *Deciphered = AllocateMemory( Size - 16 )
      If *Deciphered
        AESDecoder( *Base64 + 16, *Deciphered, Size - 16, @Key$, 256, *IV, #PB_Cipher_CBC )
        Deciphered$ = PeekS( *Deciphered )
        FreeMemory( *Deciphered )
      EndIf
      FreeMemory( *IV )
      FreeMemory( *Base64 )
      FreeMemory( *Buffer )
    EndIf
  EndIf
  ProcedureReturn Deciphered$
EndProcedure

OpenCryptRandom()

Define String$ = "Hallo Welt + Hallo Welt + Hallo Welt"
Debug String$
String$ = StringEncoder( String$, "Test" )
Debug String$
String$ = StringDecoder( String$, "Test" )
Debug String$ 

Re: AES Verschlüsselung für Strings

Verfasst: 08.09.2010 12:52
von STARGÅTE
Danke für den Code, nimmt einem das Denken ab, wenn man einfach nur verschlüssel will.

Hinweis: Dein Code funktioniert nur im Ascii-Modus, nicht unter Unicode!
Problem könnte String$ = LSet( String$, Size ) machen, dort wird die Länge in Characters erwartet, nicht Bytes!

Re: AES Verschlüsselung für Strings

Verfasst: 08.09.2010 13:52
von Christian+
Oh stimmt das ist nicht gut String$ = LSet( String$, Size ) da habe ich wohl nicht aufgepasst lässt sich aber mit String$ = String$ + Space( 16 ) ersetzen geht ja nur darum dass der String lang genug ist.

Re: AES Verschlüsselung für Strings

Verfasst: 08.09.2010 14:15
von STARGÅTE
Verstehe, daher auch diese "Umwege" mit dem mitspeichern der Länge, damit man bei kleinen Strings auch wieder das richtig herausbekommt, ohne den zusatz der Spaces ...

Re: AES Verschlüsselung für Strings

Verfasst: 08.09.2010 20:33
von Christian+
So nachdem der alte Quellcode ja bei weitem nicht Unicode tauglich war da oft Bytes und Zeichen gleichgesetzt waren habe ich das jetzt nochmal überarbeitet sollte auch wenn ich es nicht getestet habe jetzt Unicode unterstützen und dazuhin kleinere Verschlüsselte Strings erzeugen da nun auf das mitspeichern der Länge verzichtet wird hatte das irgendwie umständlich gelöst mache guten Ideen kommen halt erst beim zweiten Versuch.

Re: AES Verschlüsselung für Strings

Verfasst: 08.09.2010 21:13
von STARGÅTE
Ja gut, immerhin schlüsselt er nun richtig hin und zurück,
jedoch ist das verschlüsselte nicht mehr "verwendbar"
Hallo Welt + Hallo Welt + Hallo Welt
????????????????????????????????????????????????????????????
Hallo Welt + Hallo Welt + Hallo Welt
Problem ist, dass Base64Encoder einen String (Also das zeug im Ausgabespeicher) im Ascii-Modus zurück gibt und Unicode dann aus zwei Asciis ein Unicodezeichenbaut was "unkenntlich" ist, diesen müsstest du erst noch ins Unicode konvertieren:

zB beim Encoder so:

Code: Alles auswählen

        If *Base64
          Size = Base64Encoder( *Ciphered, Size + 16, *Base64, Size * 1.35 + 64 )
          Ciphered$ = PeekS( *Base64, Size, #PB_Ascii) ; << Ascii !
          FreeMemory( *Base64 )
        EndIf
(Damit wird das Codierte natürlich doppenlt so groß)

und beim Decoder müsstest du dann den Unicode-String erst als Ascii in ein Buffer schreiben und dann von Base64Decoder bearbeiten lassen:

Code: Alles auswählen

      *Buffer = AllocateMemory(Size)
      PokeS(*Buffer, String$, StringByteLength(String$, #PB_Ascii), #PB_Ascii)
      Size = Base64Decoder( *Buffer, Size/2, *Base64, Size * 1.3 + 64 )
Im übrigen muss der Speicher nur bei Base64Encoder 35% größer sein, bei Base64Decoder kann er kleiner sein!

Code: Alles auswählen

EnableExplicit

Procedure.s StringEncoder( String$, Key$ )
  Protected Size.l, *Input, *IV, *Ciphered, *Base64, Ciphered$
  If String$
    Size = StringByteLength( String$ ) + SizeOf(Character)
    If Size < 16 : Size = 16 : EndIf
    *Input = AllocateMemory( Size )
    If *Input
      PokeS( *Input, String$ )
      Key$ = MD5Fingerprint( @Key$, StringByteLength( Key$ ) )
      *IV = AllocateMemory( 16 )
      CryptRandomData( *IV, 16 )
      *Ciphered = AllocateMemory( Size + 16 )
      If *Ciphered
        CopyMemory( *IV, *Ciphered, 16 )
        AESEncoder( *Input, *Ciphered + 16, Size, @Key$, 256, *IV, #PB_Cipher_CBC )
        *Base64 = AllocateMemory( Size * 1.35 + 64 )
        If *Base64
          Size = Base64Encoder( *Ciphered, Size + 16, *Base64, Size * 1.35 + 64 )
          Ciphered$ = PeekS( *Base64, Size, #PB_Ascii)
          FreeMemory( *Base64 )
        EndIf
        FreeMemory( *Ciphered )
      EndIf
      FreeMemory( *IV )
      FreeMemory( *Input )
    EndIf
  EndIf
  ProcedureReturn Ciphered$
EndProcedure

Procedure.s StringDecoder( String$, Key$ )
  Protected Size.l, *IV.l, *Deciphered, *Base64, Deciphered$, *Buffer
  If String$
    Size = StringByteLength( String$ )
    *Base64 = AllocateMemory( Size * 1.3 + 64 )
    If *Base64
      *Buffer = AllocateMemory(Size)
      PokeS(*Buffer, String$, StringByteLength(String$, #PB_Ascii), #PB_Ascii)
      Size = Base64Decoder( *Buffer, StringByteLength(String$, #PB_Ascii), *Base64, Size + 64 )
      Key$ = MD5Fingerprint( @Key$, StringByteLength( Key$ ) )
      *IV = AllocateMemory( 16 )
      CopyMemory( *Base64, *IV, 16 )
      *Deciphered = AllocateMemory( Size - 16 )
      If *Deciphered
        AESDecoder( *Base64 + 16, *Deciphered, Size - 16, @Key$, 256, *IV, #PB_Cipher_CBC )
        Deciphered$ = PeekS( *Deciphered )
        FreeMemory( *Deciphered )
      EndIf
      FreeMemory( *IV )
      FreeMemory( *Base64 )
      FreeMemory( *Buffer )
    EndIf
  EndIf
  ProcedureReturn Deciphered$
EndProcedure

OpenCryptRandom()

Define String$ = "Hallo Welt + Hallo Welt + Hallo Welt"
Debug String$
String$ = StringEncoder( String$, "Test" )
Debug String$
String$ = StringDecoder( String$, "Test" )
Debug String$ 
Der Funktioniert nun im Ascii
Hallo Welt + Hallo Welt + Hallo Welt
jatCtCBty4UzQvEVyVD7Q9l/R7rCj64LORFFrsePpcU7DgovPzthLLMembZXXVQD/tZbhUU=
Hallo Welt + Hallo Welt + Hallo Welt
und Unicode!
Hallo Welt + Hallo Welt + Hallo Welt
l/A7OFqR9LnWJPRMXdLTRAph1PzX8CDNBX+RCn8JTqZJoqFRb7wtZOdvIT67lepqmDIadx/nvyVC3iirQaicH1kZKMU4isybhfdr43JtLFmjvJyeyCkpuhJd
Hallo Welt + Hallo Welt + Hallo Welt
Im Unicode ist das Verschlüsselte deshalb länger, weil er hat immer 2Byte (ein zeichen) verschlüsselt und Base daraus dann das alphanumerische macht.

Re: AES Verschlüsselung für Strings

Verfasst: 09.09.2010 08:06
von Christian+
@STARGÅTE
Danke für die Anpassungen. Beim Decoder sollte nun aber Size = StringByteLength( String$ ) zu Size = StringByteLength(String$, #PB_Ascii) + SizeOf(Character) geändert werden da sonst im Unicode Modus zu viel Speicher und im Ascii zu wenig Speicher Reserviert wird.
Wegen dem größeren Speicher bei Base64Decoder in der Hilfe steht dass er zwar kleiner sein kann es aber empfehlenswert ist einen um etwa 30% größeren zu verwenden und da ich den Base64Decoder bisher nicht allzu oft gebraucht und deswegen nicht sagen kann ob man darauf verzichten kann dachte ich mach ich mal Sicherheitshalber die 30% dazu schaden tut es ja nicht. Wenn die aber doch unötig sind dann lass ich das weg *Base64 = AllocateMemory( Size * 1.3 + 64 ) muss dann halt auch noch zu AllocateMemory( Size + 64 ) geändert werden.
Habe das gleich mal alles noch angepasst und meinen Code Aktuallisiert.

Re: AES Verschlüsselung für Strings

Verfasst: 09.09.2010 12:13
von STARGÅTE
Wegen dem Base64 noch mal:

Base64Decoder:
"Der 'AusgabePuffer' kann bis zu 33% kleiner als der Eingabepuffer sein, mit einer minimalen Größe von 64 Bytes."

Base64Encoder:
"Der 'AusgabePuffer' sollte mindestens 33% größer als der 'EingabePuffer' sein, mit einer minimalen Größe von 64 Bytes."

Auf jeden Fall ist es ichtig beim Codieren mehr Speicher zu geben, was beim Decodieren pasiert ist "eigentlich" egal.
Gleichgroß + 64 Byte ist voll in Ordnung.
Wieso jedoch mindestens diese 64Byte auf beiden Seiten nötig sind, ist mir unklar.
Zumal Base64 effektiv aus 3 Bytes genau 4 Bytes macht.

Aber nun gut. Dein Code läuft nun :allright: