F#生成MD5字典

之前想到的一种逆向思维求解MD5的方法.

后来发现真的有人这么做了, 其中数据量最大的网站标称自己拥有4T的数据量, 可以解8位以下的数字和字母组合.

即然是之前自己有过的想法, 那就拿F#来具体实现一下吧:

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
#light
namespace ViTarn
module MD5
open System
open System.Data
open System.Diagnostics
open System.IO
open System.Security.Cryptography
open System.Text
// sqlite.phxsoftware.com
#r "System.Data.SQLite.DLL"
open System.Data.SQLite
// 数据库名
let dbFile = "db.sqlite"
// 连接字符串
let connString =
let csb = SQLiteConnectionStringBuilder ()
csb.DataSource <- dbFile
csb.ConnectionString
// 秒表
let watch = new Stopwatch ()
watch.Start()
// 为调试方便 输出对象并换行
let debug x =
x |> print_any
Console.WriteLine ()
// 从\' \'到\'~\'共95个常用于密码的字符 可以当成95进制看待
let n2cl n =
let rec prase n l =
let d = n % 95
let c = d + 32 |> char
let d = n - d
if d > 95 then
prase (d / 95) (c :: l)
else
c :: l |> List.to_array prase n []
// MD5加密字符串
let md5 (str : string) =
use md5Hasher = MD5.Create ()
str
|> Encoding.Default.GetBytes
|> md5Hasher.ComputeHash
|> Seq.map (fun x ->
x.ToString "x2")
|> Seq.fold (fun x y -> x + y) ""
// 创建数据库
if dbFile |> File.Exists |> not then
dbFile |> SQLiteConnection.CreateFile
use conn = new SQLiteConnection (connString)
let sql = "PRAGMA auto_vacuum = 1; " +
"PRAGMA encoding = \'UTF-8\'; " +
"PRAGMA page_size = 4096; " +
"PRAGMA synchronous = OFF; " +
"CREATE TABLE md5 (p VARCHAR(42) NOT NULL COLLATE NOCASE, s VARCHAR(9) NOT NULL COLLATE NOCASE);"
use cmd = new SQLiteCommand (sql, conn)
conn.Open ()
cmd.ExecuteNonQuery () |> ignore
conn.Close ()
let main _ =
let sql = "INSERT INTO md5 " +
"VALUES(?, ?); "
use conn = new SQLiteConnection (connString)
use cmd = new SQLiteCommand(sql, conn)
cmd.Parameters.AddRange [|new SQLiteParameter(); new SQLiteParameter()|]
conn.Open ()
use tr = conn.BeginTransaction ()
cmd.Transaction <- tr
for i = 0 to 857374 do
let s = new String (n2cl i)
let p = md5 s
cmd.Parameters.[0].Value <- p
cmd.Parameters.[1].Value <- s
cmd.ExecuteNonQuery () |> ignore
if i % 10000 = 0 then
i |> debug
tr.Commit()
conn.Close ()
main ()
watch.Elapsed |> debug
Console.ReadKey()

为什么是857374? 95 95 95 - 1 = 857374

模拟的95进制, 是从空格(\’ \’)到波浪线(\’~\’)的, 用ASCII表示就是32到126. 所在0 to 857374代表\’ \’到\’~~~\’

在我的电脑上耗时00:01:08

  • CPU: AMD3000+
  • RAM: 1G

以DEBUG模式运行 最终产生的数据库约36M+