Thread Frage zu crypt (12 answers)
Opened by kean at 2009-03-06 10:48

betterworld
 2009-03-11 16:44
#602 #602
User since
2009-03-09
16 Artikel

user image
So, nur zum Spaß hab ich jetzt mal eine Funktion geschrieben, die das tut, was crypt() aus der glibc tut:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/perl
use strict;
use warnings;
use Digest::MD5 qw(md5);


sub mycrypt {
    my ($plain, $salt) = @_;

    $salt =~ m#^\$1\$([^\$]*)#
        or return crypt($plain, $salt);
    $salt = $1;

    # chr() und ord() etc. sollen utf8 ignorieren
    use bytes;

    # Zunaechst eine MD5-Summe aus $plain und $salt und noch einmal $plain
    # bauen:
    my $res = md5($plain . $salt . $plain);

    # Fuer jedes Zeichen aus $plain kommt ein Zeichen aus der berechneten
    # MD5-Summe:
    my $resmult = $res x (length($plain) / 16 + 1);
    chop $resmult while length($resmult) > length($plain);

    # Nun bauen wir eine neue MD5-Summe mit komischen Berechnungen aus den
    # bisherigen Ergebnissen.
    my $str1 = $plain . '$1$' . $salt . $resmult;
    for (my $i=length($plain); $i > 0; $i >>= 1) {
        # Der Kommentar in der glibc sagt, dass dies vermutlich nicht genau so
        # simpel beabsichtigt war, aber in der urspruenglichen Implementation
        # effektiv so herauskam.
        $str1 .= $i % 2 ? chr(0) : chr ord $plain;
    }
    $res = md5($str1);

    # Damit das alles auch recht lange dauert (und nicht so schnell zu knacken
    # ist), bauen wir in einer Schleife andauernd neue MD5-Summen aus der
    # jeweils vorherigen Summe sowie $plain und $salt
    for my $j (0..999) {
        my $str2 = '';

        $str2 .= $j % 2 ? $plain : $res;
        $str2 .= $salt  if $j % 3;
        $str2 .= $plain if $j % 7;
        $str2 .= $j % 2 ? $res : $plain;

        $res = md5($str2);
    }

    # Nun ist das Ergebnis schon berechnet, es muessen die Bytes nur noch in
    # seltsamer Reihenfolge mit Base64 kodiert werden.

    my $binbuf = '';
    my @order = (0, 6, 12,
                 1, 7, 13,
                 2, 8, 14,
                 3, 9, 15,
                 4, 10,
                 5, undef, 11);
    for my $idx (@order) {
        $binbuf .= defined ($idx) ? sprintf('%08b', ord substr($res, $idx, 1)) : '0000';
    }
    my $txtbuf = '';
    my @b64t = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
    while ($binbuf =~ m/(.{24}|.{12})/g) {
        $txtbuf .= $b64t[oct "0b$_"] for reverse $1 =~ /.{6}/g;
    }

    return join '$', '', 1, $salt, $txtbuf;
}


# Geht ueberall
print my $x = mycrypt('hallo welt', '$1$salt'), "\n";

# Geht nur unter Linux
print crypt('hallo welt', '$1$salt'), "\n";

# Und das Passwort ueberpruefen:
if (mycrypt('hallo welt', $x) eq $x) {
    print "Passwort richtig!\n";
}


Die Lizenz dieses Codes müsste dann wohl LGPL sein.

Diese Subroutine sollte man dann am besten noch mit einem Code kombinieren, der zufällige Salts erzeugt.
Last edited: 2009-03-11 23:13:19 +0100 (CET)

View full thread Frage zu crypt