一句话和6位PIN转换成强密码
一句话和6位PIN转换成强密码
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
import argparse
import hashlib
# 固定字符集
LOWER = "abcdefghijklmnopqrstuvwxyz"
UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DIGIT = "0123456789"
SYMB = "@"
POOL = LOWER + UPPER + DIGIT + SYMB
def phrase_to_password(phrase: str, pin: str, length: int = 10, rounds: int = 100_000) -> str:
if length < 4:
raise ValueError("length 至少为 4(需要覆盖四类字符)。")
if not (pin.isdigit() and len(pin) == 6):
raise ValueError("PIN 必须是 6 位数字。")
# 派生足够多的字节
dklen = max(length, 64)
dk = hashlib.pbkdf2_hmac(
"sha256",
phrase.encode("utf-8"),
pin.encode("utf-8"), # 使用 6 位 PIN 作为 salt
rounds,
dklen=dklen
)
# 确保四类字符各一个
picks = [
LOWER[dk[0] % len(LOWER)],
UPPER[dk[1] % len(UPPER)],
DIGIT[dk[2] % len(DIGIT)],
SYMB [dk[3] % len(SYMB )],
]
# 剩余位置从全集补齐
for i in range(4, length):
picks.append(POOL[dk[i % len(dk)] % len(POOL)])
# 洗牌
j = 0
for i in range(length - 1, 0, -1):
j = (j + 1) % len(dk)
k = dk[j] % (i + 1)
picks[i], picks[k] = picks[k], picks[i]
return "".join(picks)
def main():
parser = argparse.ArgumentParser(description="把一句话 + 6位PIN 转换成强密码")
parser.add_argument("phrase", help="输入的句子")
parser.add_argument("pin", help="6位数字 PIN 作为 salt")
parser.add_argument("--length", type=int, default=10, help="密码长度,默认10")
args = parser.parse_args()
pwd = phrase_to_password(args.phrase, args.pin, args.length)
print(pwd)
if __name__ == "__main__":
main()
如何运行脚本
保存成 genpwd.py
1
2
HISTFILE=/dev/null bash
python3 genpwd.py 我就记住这句话和一个6为PIN就能得到密码 123456
注意一定要使用HISTFILE=/dev/null bash,否则history里会记录密码导致泄露
加密脚本
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
import argparse
import base64
import hashlib
import getpass
from cryptography.fernet import Fernet
# 从密码生成 Fernet key
def password_to_key(password: str) -> bytes:
digest = hashlib.sha256(password.encode()).digest()
return base64.urlsafe_b64encode(digest)
# 加密文件
def encrypt_file(filename: str, key: bytes):
fernet = Fernet(key)
with open(filename, "rb") as file:
original = file.read()
encrypted = fernet.encrypt(original)
with open(filename + ".enc", "wb") as encrypted_file:
encrypted_file.write(encrypted)
print(f"加密完成: {filename} → {filename}.enc")
# 解密文件
def decrypt_file(filename: str, key: bytes):
fernet = Fernet(key)
with open(filename, "rb") as enc_file:
encrypted = enc_file.read()
try:
decrypted = fernet.decrypt(encrypted)
except Exception:
print("错误:无法解密文件。可能是密码错误、文件损坏或该文件不是有效的加密文件。")
exit(1)
out_file = filename[:-4] # 去掉 .enc
with open(out_file, "wb") as dec_file:
dec_file.write(decrypted)
print(f"解密完成: {filename} → {out_file}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="文件加解密工具 (基于 cryptography.Fernet)")
parser.add_argument("filename", help="要加密/解密的文件")
args = parser.parse_args()
# 安全地输入密码(不会显示在屏幕、history、ps 里)
password = getpass.getpass("请输入密码: ")
key = password_to_key(password)
if args.filename.endswith(".enc"):
decrypt_file(args.filename, key)
else:
encrypt_file(args.filename, key)
保存成 encrypt.py
1
python3 encrypt.py 要加/解密的文件
一句话和6位PIN转换成12/24助记词
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
import argparse
from hashlib import sha256
from mnemonic import Mnemonic
def check_pin(pin_str):
"""验证 PIN 是否是 6 位数字"""
if not pin_str.isdigit() or len(pin_str) != 6:
raise argparse.ArgumentTypeError("PIN 必须是 6 位数字")
return pin_str
def generate_mnemonic(sentence, pin, length=12, lang="english"):
"""
根据一句话和 PIN 生成固定助记词
:param sentence: 输入句子
:param pin: PIN码(6位数字)
:param length: 助记词长度 12 或 24
:param lang: 语言,默认英文
:return: 助记词字符串
"""
if length not in (12, 24):
raise ValueError("助记词长度只能是 12 或 24")
combined = f"{sentence}-{pin}"
hash_bytes = sha256(combined.encode('utf-8')).digest()
mnemo = Mnemonic(lang)
entropy_bytes = hash_bytes[:16] if length == 12 else hash_bytes
mnemonic_phrase = mnemo.to_mnemonic(entropy_bytes)
return mnemonic_phrase
def main():
parser = argparse.ArgumentParser(description="根据一句话和 6 位 PIN 生成 BIP39 助记词")
parser.add_argument("sentence", help="一句话")
parser.add_argument("pin", type=check_pin, help="6 位数字 PIN")
parser.add_argument("--length", type=int, default=24, choices=[12,24], help="助记词长度,12 或 24")
parser.add_argument("--lang", default="english", choices=["english","chinese_simplified"], help="助记词语言")
args = parser.parse_args()
mnemonic_phrase = generate_mnemonic(args.sentence, args.pin, args.length, args.lang)
print("生成的助记词:")
print(mnemonic_phrase)
if __name__ == "__main__":
main()
使用密码混淆单词句子
助记词使用这个程序混淆后再抄写到纸上。只有纸条也没什么用。需要加上密码和函数才能解密真的助记词
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
import random
class HashTool:
def __init__(self, pin=None):
"""
初始化工具类,可以选择传入一个 PIN。
如果未传入 PIN,则会随机生成一个。
"""
self.pin = pin if pin else self.generate_pin()
def generate_pin(self, length=8):
"""
生成一个随机 PIN,默认长度为 8。
"""
return ''.join(random.choices('0123456789', k=length))
def encrypt(self, word):
"""
使用 PIN 对输入的单词进行加密。
:param word: 原始单词
:return: 加密后的单词
"""
random.seed(self.pin) # 使用 PIN 作为随机种子
mapping = self._generate_mapping()
return ''.join(mapping[char] if char in mapping else char for char in word)
def decrypt(self, word):
"""
使用 PIN 对加密后的单词进行解密。
:param word: 加密后的单词
:return: 解密后的原始单词
"""
random.seed(self.pin) # 使用 PIN 作为随机种子
mapping = self._generate_mapping()
reverse_mapping = {v: k for k, v in mapping.items()}
return ''.join(reverse_mapping[char] if char in reverse_mapping else char for char in word)
def _generate_mapping(self):
"""
根据随机种子生成字符映射表。
:return: 字符映射表
"""
chars = list('abcdefghijklmnopqrstuvwxyz')
shuffled = chars[:]
random.shuffle(shuffled)
return dict(zip(chars, shuffled))
if __name__ == "__main__":
import getpass
print("欢迎使用可逆哈希工具!")
while True:
pin = getpass.getpass("请输入密码(不会显示在屏幕上): ")
confirm_pin = getpass.getpass("请再次输入密码以确认: ")
if pin == confirm_pin:
print("密码设置成功!")
break
else:
print("两次输入的密码不一致,请重试!")
tool = HashTool(pin=pin)
try:
while True:
word = input("\n请输入单词(加密/解密): ")
encrypted = tool.encrypt(word)
decrypted = tool.decrypt(word)
print(f"加密结果: {encrypted}")
print(f"解密结果: {decrypted}")
except KeyboardInterrupt:
print("\n已退出程序,感谢使用!")
本文由作者按照 CC BY 4.0 进行授权