aianyu commited on
Commit
48ccb12
·
verified ·
1 Parent(s): 2d31d2c

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +8 -7
  2. app.py +179 -0
  3. requirements.txt +2 -0
  4. wallet.dat +0 -0
README.md CHANGED
@@ -1,12 +1,13 @@
1
  ---
2
- title: B
3
- emoji: 🔥
4
- colorFrom: pink
5
- colorTo: green
6
- sdk: gradio
7
- sdk_version: 5.31.0
 
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: BTC Wallet
3
+ emoji: 👛
4
+ colorFrom: blue
5
+ colorTo: yellow
6
+ python_version: 3.9.2
7
+ sdk: streamlit
8
+ sdk_version: 1.26.0
9
  app_file: app.py
10
  pinned: false
11
  ---
12
 
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from pywallet import wallet
3
+ import time
4
+ import itertools
5
+ import string
6
+
7
+ # --- 配置 ---
8
+ # 密码字符集(仅用于基本暴力破解,非常不推荐用于实际钱包)
9
+ DEFAULT_CHARSET = string.ascii_lowercase + string.digits # a-z, 0-9
10
+ MAX_BRUTEFORCE_LEN = 4 # 限制暴力破解长度,否则会永远运行
11
+
12
+ # --- 辅助函数 ---
13
+ def try_decrypt_wallet(wallet_data_bytes, password_attempt):
14
+ """
15
+ 尝试用给定的密码解密钱包。
16
+ 返回 True 如果成功, False 如果失败。
17
+ """
18
+ try:
19
+ # pywallet 需要一个文件名或类文件对象,但我们可以从字节加载
20
+ # 为了安全和简单,我们避免将钱包数据写入临时文件
21
+ # 但 pywallet.Wallet.from_binary() 似乎是存在的
22
+ w = wallet.Wallet.from_binary(wallet_data_bytes)
23
+
24
+ if w.is_encrypted():
25
+ if w.decrypt(password_attempt):
26
+ # 解密成功!
27
+ return True
28
+ else:
29
+ # 密码错误
30
+ return False
31
+ else:
32
+ # 钱包未加密
33
+ st.info("钱包文件未加密。")
34
+ return True # 可以认为是一种“成功”
35
+ except Exception as e:
36
+ # st.error(f"解密时发生错误: {e}") # 调试时可以取消注释
37
+ # 常见的错误可能是密码错误导致解密失败,或者钱包文件损坏
38
+ return False
39
+
40
+ def generate_passwords_bruteforce(charset, max_len):
41
+ """
42
+ (非常不推荐) 基本的暴力破解密码生成器
43
+ """
44
+ for length in range(1, max_len + 1):
45
+ for item in itertools.product(charset, repeat=length):
46
+ yield "".join(item)
47
+
48
+ # --- Streamlit UI ---
49
+ st.set_page_config(page_title="Wallet.dat Cracker", layout="wide")
50
+ st.title("Bitcoin Wallet.dat 密码破解尝试工具 (教育目的)")
51
+
52
+ st.warning(
53
+ """
54
+ **重要声明:**
55
+ 1. 此工具仅用于恢复 **您自己** 的钱包密码。
56
+ 2. 破解过程 **极其缓慢**,对复杂密码几乎无效。
57
+ 3. **请勿将您的真实钱包文件上传到不受信任的在线服务。此工具应在本地运行。**
58
+ 4. 对于任何数据丢失或法律问题,作者概不负责。
59
+ """
60
+ )
61
+
62
+ # --- 文件上传 ---
63
+ uploaded_wallet_file = st.file_uploader("1. 上传你的 wallet.dat 文件", type=["dat"])
64
+
65
+ if uploaded_wallet_file:
66
+ wallet_bytes = uploaded_wallet_file.getvalue()
67
+ st.success(f"已上传 {uploaded_wallet_file.name} ({len(wallet_bytes)} bytes)")
68
+
69
+ # --- 破解方法选择 ---
70
+ crack_method = st.radio(
71
+ "2. 选择破解方法:",
72
+ ('使用密码列表', '尝试单个密码', '基本暴力破解 (非常不推荐,极慢)')
73
+ )
74
+
75
+ # --- 密码列表方法 ---
76
+ if crack_method == '使用密码列表':
77
+ uploaded_password_list = st.file_uploader(
78
+ "上传密码列表文件 ( .txt, 每行一个密码)", type=["txt"]
79
+ )
80
+ if uploaded_password_list:
81
+ passwords_to_try = [
82
+ line.strip() for line in uploaded_password_list.read().decode().splitlines() if line.strip()
83
+ ]
84
+ st.info(f"密码列表加载了 {len(passwords_to_try)} 个密码。")
85
+
86
+ if st.button("开始使用列表破解", key="list_crack"):
87
+ if not passwords_to_try:
88
+ st.error("密码列表为空。")
89
+ else:
90
+ st.info("开始破解尝试...")
91
+ progress_bar = st.progress(0)
92
+ status_text = st.empty()
93
+ found_password = None
94
+ start_time = time.time()
95
+
96
+ for i, pwd in enumerate(passwords_to_try):
97
+ status_text.text(f"尝试密码 ({i+1}/{len(passwords_to_try)}): {pwd}")
98
+ if try_decrypt_wallet(wallet_bytes, pwd):
99
+ found_password = pwd
100
+ break
101
+ progress_bar.progress((i + 1) / len(passwords_to_try))
102
+ # 在 Streamlit 中添加少量延迟以允许 UI 更新,尤其是在快速循环中
103
+ # time.sleep(0.001)
104
+
105
+
106
+ end_time = time.time()
107
+ status_text.text("破解尝试完成。")
108
+ elapsed_time = end_time - start_time
109
+
110
+ if found_password:
111
+ st.success(f"🎉 密码找到: **{found_password}** 🎉")
112
+ st.balloons()
113
+ else:
114
+ st.error("未能在密码列表中找到正确的密码。")
115
+ st.write(f"总耗时: {elapsed_time:.2f} 秒。")
116
+ st.write(f"平均速度: {len(passwords_to_try) / elapsed_time if elapsed_time > 0 else float('inf'):.2f} 密码/秒。")
117
+
118
+
119
+ # --- 单个密码方法 ---
120
+ elif crack_method == '尝试单个密码':
121
+ single_password = st.text_input("输入要尝试的密码:", type="password")
122
+ if st.button("尝试此密码", key="single_crack"):
123
+ if not single_password:
124
+ st.warning("请输入密码。")
125
+ else:
126
+ st.info(f"正在尝试密码: {single_password}")
127
+ if try_decrypt_wallet(wallet_bytes, single_password):
128
+ st.success(f"🎉 密码正确: **{single_password}** 🎉")
129
+ st.balloons()
130
+ else:
131
+ st.error("密码错误。")
132
+
133
+ # --- 基本暴力破解方法 ---
134
+ elif crack_method == '基本暴力破解 (非常不推荐,极慢)':
135
+ charset_input = st.text_input("字符集:", DEFAULT_CHARSET)
136
+ max_len_input = st.number_input("最大密码长度 (警告: 长度大于4会非常慢):", min_value=1, max_value=8, value=MAX_BRUTEFORCE_LEN)
137
+
138
+ st.warning(f"使用字符集 '{charset_input}' 和最大长度 {max_len_input} 进行暴力破解,"
139
+ f"可能需要尝试 {sum(len(charset_input)**i for i in range(1, max_len_input + 1))} 个密码。")
140
+
141
+ if st.button("开始暴力破解 (请耐心等待)", key="brute_crack"):
142
+ st.info("开始暴力破解尝试...")
143
+ # 无法预估总数,因此不使用标准进度条
144
+ status_text = st.empty()
145
+ found_password = None
146
+ start_time = time.time()
147
+ count = 0
148
+ estimated_total = sum(len(charset_input)**i for i in range(1, max_len_input + 1))
149
+ progress_bar = st.progress(0)
150
+
151
+
152
+ for pwd in generate_passwords_bruteforce(charset_input, max_len_input):
153
+ count += 1
154
+ status_text.text(f"尝试密码 #{count}: {pwd}")
155
+ if try_decrypt_wallet(wallet_bytes, pwd):
156
+ found_password = pwd
157
+ break
158
+ if count % 100 == 0: # 每100次更新一次进度条,避免过于频繁
159
+ progress_bar.progress(min(1.0, count / estimated_total if estimated_total > 0 else 0))
160
+ # time.sleep(0.001) # 允许UI更新
161
+
162
+
163
+ end_time = time.time()
164
+ status_text.text("暴力破解尝试完成。")
165
+ elapsed_time = end_time - start_time
166
+
167
+ if found_password:
168
+ st.success(f"🎉 密码找到: **{found_password}** 🎉")
169
+ st.balloons()
170
+ else:
171
+ st.error(f"在指定的字符集和长度内未能找到密码 (尝试了 {count} 个)。")
172
+ st.write(f"总耗时: {elapsed_time:.2f} 秒。")
173
+ st.write(f"平均速度: {count / elapsed_time if elapsed_time > 0 else float('inf'):.2f} 密码/秒。")
174
+
175
+ else:
176
+ st.info("请先上传 wallet.dat 文件。")
177
+
178
+ st.markdown("---")
179
+ st.markdown("免责声明:此工具仅供教育和个人恢复目的。请负责任地使用。")
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ pywallet
2
+ streamlit
wallet.dat ADDED
Binary file (24.6 kB). View file