VB-Tec.de Visual Basic - Technik, FAQ, Tricks, BeispieleHome / Allgemein / Sicherheit / Encode Strings schnell ver- und entschlüsseln |
| Historie | |
|---|---|
| 27.08.2007 | Behandeln eines StrConv-Bugs, welcher bei leeren Zeichenketten auftritt. Vielen Dank an Manuel Ratzinger für den entsprechenden Fehler-Hinweis! |
| 06.06.2005 | Debugging; Umstellung auf (etwas langsameres aber robustes) Verfahren via StrConv-Funktion |
| 22.09.2001 | Erste Version benutzt Speichermapping |
Für viele Anwendungsbereiche wird eine schnelle Verschlüsselung benötigt: Ob zur Speicherung von Passwörtern in Datenbanken, oder zur Unkenntlichmachung von Texten oder beliebigen Dateien.
Die unten vorgestellten Routinen erfüllen zumindest folgende Anforderungen:
Nachfolgend wird u.a. gezeigt, wie ein Byte-Array verschlüsselt werden kann, und wie dies dazu genutzt werden kann, einen String schnell zu verschlüsseln.
Einen Text mit Passwort "abc" verschlüsseln und anschließend wieder entschlüsseln:
Dim s As String s = "Hallo Welt!" EncodeString s, "abc" 'das (unleserliche) Ergebnis steht in s EncodeString s, "abc" 'jetzt steht wieder "Hallo Welt!" in s
Via Funktion verschlüsselten Text hexadezimal anzeigen:
MsgBox HexDump(EncodeStr("Hallo", "abc")) 'zeigt "B69D3F3F3F" an
Ein Byte-Array verschlüsseln (am fiktiven Beispiel einer Binärdatei):
Dim b() As Byte 'ReadData "c:\test\bla.exe", b EncodeArrayB b, "abc" 'WriteData "c:\test\bla.exe", b
Das Herzstück der Verschlüsselung (der eigentliche Algorithmus) ist hier zu finden: Ein gegebenes Byte-Array wird Byte für Byte durch Anwendung der Xor-Funktion verschlüsselt. Da die zweimalige Anwendung von Xor (mit dem gleichen Wert) den ursprünglichen Wert wiederherstellt, ist die Entschlüsselung mit dieser Routine ebenfalls möglich.
Public Sub EncodeArrayB( _
ByRef ByteArray() As Byte, _
Optional ByRef Password As String _
)
Const MagicByte As Byte = &HFF
Dim PwdLen As Long
Dim PwdAsc As Byte
Dim i As Long
Dim j As Long
Dim LB As Long
Dim UB As Long
PwdLen = Len(Password)
Select Case PwdLen
Case 0 'Kein Password verwenden:
For i = LBound(ByteArray) To UBound(ByteArray)
ByteArray(i) = ByteArray(i) Xor MagicByte Xor (i And &HFF)
Next i
Case 1 'Einzelnes Zeichen als Password verwenden:
PwdAsc = Asc(Password) Xor MagicByte
For i = LBound(ByteArray) To UBound(ByteArray)
ByteArray(i) = ByteArray(i) Xor PwdAsc Xor (i And &HFF)
Next i
Case Else 'Password verwenden:
LB = LBound(ByteArray)
UB = UBound(ByteArray)
'Buchstaben-weise das Passwort durchlaufen:
For j = 1 To PwdLen
PwdAsc = Asc(Mid$(Password, j, 1)) Xor MagicByte
For i = LB To UB Step PwdLen
ByteArray(i) = ByteArray(i) Xor PwdAsc Xor (i And &HFF)
Next i
LB = LB + 1
Next j
End Select
End Sub
Man beachte, wie durch die Fallunterscheidung nach der Passwort-Länge eine optimale Performance sichergestellt wird.
Um Byte-weise auf die einzelnen Zeichen eines Strings zuzugreifen, wird der String an ein Byte-Array zugewiesen. VB würde eigentlich ein Zeichen in jeweils zwei Elemente des Byte-Arrays ablegen (wegen Unicode-Darstellung), daher muss der String vorher mit der VB-Funktion StrConv konvertiert werden (und hinterher wieder zurück).
Eine andere Idee wäre der Zeichen-weise Zugriff via Mid$ gewesen, sowohl beim Lesen, als auch beim Schreiben. Aber im Vergleich zur direkten Operation auf Bytes (also Zahlenwerte) ist die Kodierung von Zeichen deutlich aufwändiger und langsamer; man müßte ständig die VB-Funktionen Asc und Chr$ benutzen, welche nun wirklich nicht die schnellsten sind.
Also habe ich mich für die erste Idee entschieden:
Public Sub EncodeString( _
ByRef Text As String, _
Optional ByRef Password As String _
)
Dim Bytes() As Byte
If Len(Text) Then
Bytes = StrConv(Text, vbFromUnicode)
EncodeArrayB Bytes, Password
Text = StrConv(Bytes, vbUnicode)
End If
End Sub
Die Fallunterscheidung (prüfen, ob der Text nicht leer ist) ist notwendig, da die StrConv-Funktion Probleme beim Umgang mit leeren Zeichenketten hat.
Für einzelne Fälle kann es ganz praktisch sein, den Text in der original-Variable nicht zu verändern. Daher gibt die folgende Funktion eine Kopie zurück:
Public Function EncodeStr( _
ByRef Text As String, _
Optional ByRef Password As String _
) As String
EncodeStr = Text
EncodeString EncodeStr, Password
End Function
© Jost Schwider, 22.09.2001-27.08.2007 - http://vb-tec.de/strcode.htm