Byte Array

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
pooner
User
Beiträge: 37
Registriert: Montag 15. Mai 2006, 08:04

Hallo Leute,
ich habe ein Problem und hoofe auf eure Hilfe.

Ich habe eine DB, in die per java code user und passwd geschrieben wird.
das Passwort ist kodiert md5-hash und dann base64.

Nachdem ich die Daten auslesen konnte und feststellte das das dekodieren mit base64 des passwortes einen anderen md5 -hash liefert als angenommen, bin ich fast verzweifelt. NAchdem ich mir den Source der Java-App angeschaut habe stelle ich fest das nicht der String md5 verschlüsselt wird sondern erste ein byte-array erstellt wird und das base 64 verschlüsselt wird.

Code: Alles auswählen

 byte[] b = string.getBytes();
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(b);
        byte[] digest = md.digest();
        return new String(digest);
Nun will ich das nachbauen das im prinzip ein übergebener Stringt an ein python-Skript auch in ein byte-array kommt und dann ein md5-hash gebildet wird. Diesen dann base64 kodieren und vergleichen.

Ich weiss ist umständlich, habe aber kkeine idee wie ich das mit dem byte-Array anstelle.

Danke für eure hilfe
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Strings in Python (<3.0) sind schon Byte-Arrays, da musst du nichts mehr machen.
pooner
User
Beiträge: 37
Registriert: Montag 15. Mai 2006, 08:04

okay , dann muss ich also bloss aus dem string einen hash erzeugen und dann kodieren mit base 64

mein Ansatz war

Code: Alles auswählen

import base64
import hashlib
m = hashlib.md5("passwd")

enc_passwd = base64.encodestring(m)


was bei der base64 codierung mit fehlern abgebrochen ist.

Ideen dazu ??
n4p
User
Beiträge: 55
Registriert: Dienstag 10. Juni 2008, 11:05

m ist kein String

Code: Alles auswählen

>>> m
'<md5 HASH object @ 00ABCFC0>'
Vielleicht eher so:

Code: Alles auswählen

import base64
import hashlib
m = hashlib.md5("passwd").digest()

enc_passwd = base64.encodestring(m)
pooner
User
Beiträge: 37
Registriert: Montag 15. Mai 2006, 08:04

danke habe ich gerade mit einem dem String root ausprobiert.
Erhalte als Ergebnis Y6nw6nu5gFB5a2SehUgYRQ==

leider sieht das gespeicherte Passwort in der DB so aus:
Z++/ve+/ve+/vWFoUCTvv73vv73vv71V77+977+9e++/vQ==

es wird auch nur ein byte_array erzeugt und dann base64 codiert, müsste doch also identisch sein. Sehe leider den Fehler nicht.

Habt ihr ncoh Ideen dazu?
BlackJack

Finde heraus was das Java-Programm *wirklich* macht. MD5-Prüfsummen sind 128 Bit lang, also 16 Bytes. In der Datenbank stehen aber mehr als doppelt so viele Bytes. Wo kommen die her!?
BlackJack

OMG und WTF!? Ich habe mir das Java-Snippet mal näher angeschaut. Da wird die MD5-Prüfsumme berechnet und die 16 Bytes Ergebnis werden als Zeichenkette interpretiert ─ und zwar in der Kodierung, die die Plattform verwendet, auf der das läuft. Das fällt nicht nur (lautlos) auf die Nase wenn diese Bytes etwas enthalten was nicht dekodiert werden kann, nein, das Ergebnis ist auch noch von den Zeichensatzeinstellungen des verwendeten Rechners abhängig. :shock:

Wenn man Z++/ve+/ve+/vWFoUCTvv73vv73vv71V77+977+9e++/vQ== mal Base64-dekodiert, kommen da 34 Bytes heraus, die sich ohne Fehler UTF-8 dekodieren lassen. Das sieht dann so aus:

Code: Alles auswählen

In [428]: 'Z++/ve+/ve+/vWFoUCTvv73vv73vv71V77+977+9e++/vQ=='.decode('base64')
Out[428]: 'g\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdahP$\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdU\xef\xbf\xbd\xef\xbf\xbd{\xef\xbf\xbd'

In [429]: _.decode('utf-8')
Out[429]: u'g\ufffd\ufffd\ufffdahP$\ufffd\ufffd\ufffdU\ufffd\ufffd{\ufffd'

In [430]: print _
g���ahP$���U��{�
Das sind nicht etwa nicht darstellbare Zeichen, sondern das Zeichen für nicht darstellbare Zeichen ganz ordnungsgemäss kodiert. Ich vermute mal die Plattform auf der das entstanden ist verwendet UTF-8 und das Java-Programm hat deshalb mal eben den Grossteil der Prüfsumme einfach weggeworfen, weil man beliebige Bytes eben nicht sinnvoll als UTF-8 interpretieren kann.

Wer immer das Java geschrieben hat, hat grossen unsicheren, unportablen Mist geschrieben.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Sollte man in Java den Digest nicht mit Strings updaten? Die ByteString-Geschichte erschien mir zu Anfang gleich etwas überraschend.
BlackJack

@Y0Gi: Man kann den Digest nicht mit Zeichenketten updaten, eine entsprechende Methode gibt's gar nicht. Die Prüfsumme ist über Bytes definiert und Java's Zeichenketten sind äquivalent zu `unicode`-Objekten in Python. Wie die intern dargestellt werden ist Implementierungsdetail, man muss die also erst in Bytes überführen. Und das möglichst mit einer festen Kodierung, sinnvollerweise eine die alle Unicode-Zeichen abdeckt. Und man darf das Ergebnis dann nicht einfach wieder als Zeichenkette interpretieren und *die* als Base64 kodieren, sondern man muss die Bytes selbst Base64 kodieren.

Wobei ich Base64 schon ein wenig daneben finde. Eine Darstellung als 32-stellige Hexzahl finde ich jedenfalls naheliegender und einfacher.

Der Java-Code da oben macht ungefähr das hier:

Code: Alles auswählen

    b = string.encode(sys.getfilesystemencoding())
    md = hashlib.md5(b)
    digest = md.digest()
    return digest.decode(sys.getfilesystemencoding(), 'replace')
Und das ist einfach ziemlich kaputt.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ah, danke, I can see clearly now.
pooner
User
Beiträge: 37
Registriert: Montag 15. Mai 2006, 08:04

Danke für eure Hilfe, habe mich jetzt aber mit java durchgeschlagen. läuft zwar, aber noch nicht hundertprozentig.
BlackJack

Hast Du die Probleme mit dem Java-Code verstanden und behoben? Das ist nicht plattformunabhängig und es werden Informationen von der Prüfsumme einfach weggeworfen. Aus Sicherheitssicht ist das ziemlich kaputt!
Antworten