]> gitweb.factorcode.org Git - factor.git/blob - extra/crypto/passwd-md5/passwd-md5.factor
core: Rename iota to <iota> so we can have TUPLE: iota ... ; instead of TUPLE: iota...
[factor.git] / extra / crypto / passwd-md5 / passwd-md5.factor
1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel base64 checksums.md5 sequences checksums
4 locals prettyprint math math.bits grouping io combinators
5 fry make combinators.short-circuit math.functions splitting ;
6 IN: crypto.passwd-md5
7
8 <PRIVATE
9
10 : lookup-table ( n -- nth )
11     "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" nth ; inline
12
13 : to64 ( v n -- string )
14     [ [ -6 shift ] [ 6 2^ 1 - bitand lookup-table ] bi ]
15     replicate nip ; inline
16
17 PRIVATE>
18
19 :: passwd-md5 ( magic salt password -- bytes )
20     password magic salt 3append
21     salt password dup surround md5 checksum-bytes
22     password length
23     [ 16 / ceiling swap <repetition> concat ] keep
24     head-slice append
25     password [ length make-bits ] [ first ] bi
26     '[ CHAR: \0 _ ? ] "" map-as append
27     md5 checksum-bytes :> final!
28
29     1000 <iota> [
30         "" swap
31         {
32             [ 0 bit? password final ? append ]
33             [ 3 mod 0 > [ salt append ] when ]
34             [ 7 mod 0 > [ password append ] when ]
35             [ 0 bit? final password ? append ]
36         } cleave md5 checksum-bytes final!
37     ] each
38
39     magic salt "$" 3append
40     { 12 0 6 13 1 7 14 2 8 15 3 9 5 4 10 } final nths 3 group
41     [ first3 [ 16 shift ] [ 8 shift ] bi* + + 4 to64 ] map concat
42     11 final nth 2 to64 3append ;
43
44 : parse-shadow-password ( string -- magic salt password )
45     "$" split harvest first3 [ "$" dup surround ] 2dip ;
46
47 : authenticate-password ( shadow password -- ? )
48     '[ parse-shadow-password drop _ passwd-md5 ] keep = ;