Wie wird ein String in Base64 verwandelt?

  • Hallo, ich wollte gerne fragen ob jemand eine Vorstellung darüber wie eine String zu Bae64 umgewandelt wird ?
    Ich weiß zwar, dass es fertige UDF´s dazu schon gibt, mich interessiert aber die Vorgehensweise, damit ich es selber realisieren kann. Soweit ich schon weiß, besteht das Base64 System aus 64 Zeichen

    Code
    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

    laut dem Wikipedia Artikel aber dennoch werde ich nicht schlauer dadurch. Nun hoffe ich, das mir jemand einen festeren Ansatz dazu bitte geben könnte.

    Binär und Hexadezimal System ist mir bekannt.

  • Entweder du suchst dir eine Dll die das kann, oder du bastelst dir in nativem AutoIt eine Funktion.

    Hier mal das was ich vor einiger Zeit produziert habe.

    Skript
    [autoit]

    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Version=Beta
    #AutoIt3Wrapper_Icon=..\InconTransfer32.ico
    #AutoIt3Wrapper_UseUpx=n
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

    [/autoit] [autoit][/autoit] [autoit]

    ;~ #include <WindowsConstants.au3>
    ;~ #include <EditConstants.au3>
    ;~ #include <WinApi.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $a[256] ; Enthält die Binären Zahlen von 0 bis 255
    Global $b[65] ; Das Base64 Array
    Global $r[111112] ; Das "Rückwärts6BitDezToBin" Array (Braucht leider viele Elemente. Es werden aber nur 64 genutzt)
    _ArrayFuellen() ; Füllt das binärarray und das Base64 Array

    [/autoit] [autoit][/autoit] [autoit]

    $hWnd=GUICreate('Echtzeit Base64 Umwandlung',600,300,-1)
    $hInputEdit=GUICtrlCreateEdit('',0,0,600,150,4096+64)
    $hOutputEdit=GUICtrlCreateEdit('',0,150,600,135,2048+64)
    GUICtrlSetFont(-1, 15, 400, 0 , 'Courier New', 5)
    $hLabel = GUICtrlCreateLabel('', 5, 285, 600, 15)
    GUIRegisterMsg(0x0111,"WM_COMMAND")
    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    While Not (GUIGetMsg() = -3)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func WM_COMMAND($hWinHandle,$iMsg,$wParam,$lParam)
    Local $t
    If _WinAPI_HiWord($wParam)=0x300 And _WINAPI_LoWord($wParam)=$hInputEdit Then
    Local $read = GUICtrlRead($hInputEdit)
    If Not StringReplace(StringReplace($read, '0', ''), '1', '') Then
    $t = TimerInit()
    $bEncrypted=_BinToString($read)
    $t = TimerDiff($t)
    GUICtrlSetData($hOutputEdit,$bEncrypted)
    GUICtrlSetData($hLabel, 'Base64 -> String - ' & Round($t*1000) & ' µs')
    Else
    $t = TimerInit()
    $bEncrypted=_StringToBase64($read)
    $t = TimerDiff($t)
    GUICtrlSetData($hLabel, 'String -> Base64 - ' & Round($t*1000) & ' µs')
    GUICtrlSetData($hOutputEdit,$bEncrypted)
    EndIf
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WinAPI_HiWord($iLong)
    Return BitShift($iLong, 16)
    EndFunc ;==>_WinAPI_HiWord

    [/autoit] [autoit][/autoit] [autoit]

    Func _WinAPI_LoWord($iLong)
    Return BitAND($iLong, 0xFFFF)
    EndFunc ;==>_WinAPI_LoWord

    [/autoit] [autoit][/autoit] [autoit]

    Func _StringToBase64($s)
    Local $sRet, $Tmp, $Bytes
    For $i = 1 To StringLen($s) Step 3
    $Tmp = _StringToBin(StringMid($s, $i, 3))
    $sRet &= StringLeft($b[_7BitToDec(StringLeft($Tmp, 6))] & $b[_7BitToDec(StringMid($Tmp, 7, 6))] & $b[_7BitToDec(StringMid($Tmp, 13, 6))] & $b[_7BitToDec(StringMid($Tmp, 19, 6))] & '==', 4)
    Next
    ;~ ConsoleWrite($sRet & @CRLF)
    Return $sRet
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _7BitToDec($bin)
    If $bin = '' Then Return 64
    $bin = StringLeft($bin & '00000', 6)
    ;~ ConsoleWrite($bin & ' ' & $r[$bin] & @CRLF)
    Return $r[$bin]
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _StringToBin($s) ; String rein, Nullen und Einsen raus !
    Local $h = StringTrimLeft(StringToBinary($s), 2), $r
    For $i = 1 To StringLen($s) * 2 Step 2 ; 1 Zeichen -> 2 Hex
    $r &= $a['0x' & StringMid($h, $i, 2)]
    Next
    Return $r
    EndFunc ;==>_StringToBin

    [/autoit] [autoit][/autoit] [autoit]

    Func _BinToString($b) ; Nullen und Einsen rein, String raus !
    Local $s
    For $i = 1 To StringLen($b) Step 8 ; 1 Zeichen -> 8 Bit
    Switch Int(StringMid($b, $i, 4))
    Case 0
    $s &= '0'
    Case 1
    $s &= '1'
    Case 10
    $s &= '2'
    Case 11
    $s &= '3'
    Case 100
    $s &= '4'
    Case 101
    $s &= '5'
    Case 110
    $s &= '6'
    Case 111
    $s &= '7'
    Case 1000
    $s &= '8'
    Case 1001
    $s &= '9'
    Case 1010
    $s &= 'A'
    Case 1011
    $s &= 'B'
    Case 1100
    $s &= 'C'
    Case 1101
    $s &= 'D'
    Case 1110
    $s &= 'E'
    Case 1111
    $s &= 'F'
    EndSwitch
    Switch Int(StringMid($b, $i+4, 4))
    Case 0
    $s &= '0'
    Case 1
    $s &= '1'
    Case 10
    $s &= '2'
    Case 11
    $s &= '3'
    Case 100
    $s &= '4'
    Case 101
    $s &= '5'
    Case 110
    $s &= '6'
    Case 111
    $s &= '7'
    Case 1000
    $s &= '8'
    Case 1001
    $s &= '9'
    Case 1010
    $s &= 'A'
    Case 1011
    $s &= 'B'
    Case 1100
    $s &= 'C'
    Case 1101
    $s &= 'D'
    Case 1110
    $s &= 'E'
    Case 1111
    $s &= 'F'
    EndSwitch
    Next
    Return BinaryToString('0x' & $s)
    EndFunc ;==>_BinToString

    [/autoit] [autoit][/autoit] [autoit]

    Func _DecToBin($iD) ; Modulomethode -> Nicht sehr schnell. Unwichtig, da sie nur zum Initialisieren von 0 bis 255 genutzt wird.
    Local $sR
    Do
    $sR = Mod($iD, 2) & $sR
    $iD = Floor($iD / 2)
    Until $iD = 0
    Return StringRight('0000000' & $sR, 8) ; Es werden 8 Stellen ausgegeben !
    EndFunc ;==>_DecToBin

    [/autoit] [autoit][/autoit] [autoit]

    Func _ArrayFuellen() ; Damit alle Werte von 0 bis 255 direkt vorliegen und keine Berechnungen nötig sind.
    For $i = 0 To 255 Step 1
    $a[$i] = _DecToBin($i)
    Next
    Local $sArray = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    For $i = 1 To 64 Step 1
    $b[$i - 1] = StringMid($sArray, $i, 1)
    $r[_DecToBin($i - 1)] = $i - 1
    Next
    EndFunc ;==>_ArrayFuellen

    [/autoit]

    Der Ansatz ist einfach: Aus 3x 8Bit werden 4x 6Bit (Aufgefüllt wird am Ende mit "=" Zeichen)
    Edit: Das beigelegte Skript ist ziemlich auf Tempo getrimmt. Ich weiß nicht inwiefern man daraus die Funktionalität erkennt^^

    Edit2: Ohje. Ich sollte lesen lernen.
    Ich dachte es würde nach einem Skript gefragt :pinch:

  • Ich bezweifle, dass ich das besser als Wikipedia erklären kann. Ich versuchs trotzdem mal :D.

    Base64 ist ein Stellenwertsystem genau wie Base10, unser Dezimalsystem, allerdings nicht mit einem Stellenwert von 10, sondern 64. Das heißt, wenn du eine Ziffer in diesem System nach links verschiebst ist sie danach nicht 10 mal, sondern 64 mal so groß wie vorher. Dazu braucht man logischerweise auch 64 Ziffern um all diese Werte mit einem einzigen Zeichen darstellen zu können.
    Du kannst Werte in jedes dieser Stellenwertsysteme konvertieren. Zum Beispiel von Dezimal zu Hexadezimal (Base16) oder auch ins Binärsystem. Der Wert bleibt der gleiche, nur die Darstellung ändert sich.

    Wenn du nun einen String in Base64 kodierst machst du nichts anderes. Jedes einzelne Zeichen ist im Grunde nur eine Zahl. Je nach Zeichenkodierung kann ein Zeichen auf verschiedene Arten durch einen Wert repräsentiert werden. Im Fall von ASCII werden alle 128 Zeichen (Buchstaben, Zahlen, Sonderzeichen etc.) in 7-bit im Binärsystem kodiert (wenn du alle 7-Bits mit einsen füllst bekommst du 127, zusammen mit 0 macht das 128 verschiedene Zahlen).
    Base64 ist für die Kodierung von 8-Bit Daten besonders gut geeignet. Davon kannst du nämlich immer 3-Byte der ursrünglichen Daten (1-Byte=8-Bit) aneinanderreihen und auf 4 aneinandergereihte 6-Bit Blöcke im Base64 System aufteilen. Dadurch sinkt die Anzahl der Zeichen für die Kodierung von 256 auf 64 und kann durch lesbare und verbreitete Zeichen dargestellt werden die auch mit sehr alten Systemen noch kompatibel sind. Am String ändert das nichts, bloß kann den dann kein Mensch mehr normal lesen :P.

    Falls hier Fehler drin sind, bitte ich natürlich darum mich zu verbessern.

    Edit: Das von James gefällt mir wesentlich besser. Wenn du das nicht verstehst, machst du was falsch :D.

  • Im Fall von ASCII werden alle 128 Zeichen (Buchstaben, Zahlen, Sonderzeichen etc.) in 7-bit im Binärsystem kodiert (wenn du alle 7-Bits mit einsen füllst bekommst du 127, zusammen mit 0 macht das 128 verschiedene Zahlen)..


    Ist ASCII nicht 8 bit (0 - 255)?

  • Hi,
    um mal die Frage des TE zu beantworten, klar gibts was fertiges!
    Sich mit dieser Vorlage hinzustellen und nach einer ERKLÄRUNG zu fragen, ist schon frech....