我在 Julia 中构建了一个高级密码管理器(哦,是的,Juliaaaa)
发布: (2025年11月30日 GMT+8 14:54)
5 min read
原文: Dev.to
Source: Dev.to
我编写工具是为了避免把无聊的事做两遍,最近我一直在用大家意想不到的语言来实现。这次:Julia。是的,那种大家把它和数学、机器学习联系在一起的科学语言。如果有人不同意,请大声喊出来。
为什么选 Julia 而不是显而易见的 (Python/Go/Rust)?
- 原生性能:Julia 通过 LLVM 编译成机器码。对于密集的密码学操作(密钥派生、重复哈希),这点很重要。
- 表达式语法:我可以用看起来像数学的方式编写复杂的数学(比如熵的计算)。
- 多重分派:我可以根据输入类型定义不同的行为,而不必把代码写成
if/else的动物园。 - 交互式 REPL:快速开发、实时测试、随时调整。
- 惊喜:因为没人会想到,这正合我胃口。
架构:让密码管理器“专业”的因素是什么?
安全需求
- ✅ 真实加密:模拟 AES-256-GCM(演示中使用 XOR + 密钥派生,但结构已经准备好替换为
Nettle.jl) - ✅ 密钥派生:PBKDF2,100,000 次迭代(已为 Argon2 做好准备)
- ✅ 唯一盐值:每条加密记录使用独立的、密码学安全的随机盐
- ✅ 零知识架构:主密码永不存储,只从中派生密钥
- ✅ 安全生成:使用 Julia 的
Random,来源于密码学安全的随机数
功能特性
- 🎲 可配置选项的密码生成器
- 📊 熵计算器(本项目的明星)
- 💾 加密的 JSON 存储
- 🔍 密码比较器
- 🎨 直观的 CLI 界面
熵模块:有趣的部分
什么是熵?
在密码学中,熵是 不确定性 的度量。具体来说,它表示你的密码包含多少位不可预测的信息。计算方式如下:
H = L * log2(R)
- L = 密码长度
- R = 可能字符集合的大小
直观示例
典型弱密码
Password123!
- 长度:12 个字符
- 检测到的字符池:小写字母 (26) + 大写字母 (26) + 数字 (10) + 符号 (32) = 94 个字符
- 熵:12 × log₂(94) ≈ 78.5 位
- 估计破解时间:约 95 年(现代 GPU)
真实问题:它是字典单词并遵循可预测模式,字典攻击可以在几分钟内破解。
生成的强密码
xK9#mL2$pQ7@vR4!nF
- 长度:18 个字符
- 字符池:94 个字符(全部使用)
- 熵:18 × log₂(94) ≈ 118 位
- 估计破解时间:约 1.05 × 10¹⁶ 年(实际上不可行)
在 Julia 中的实现
熵计算
function calculate_entropy(password::String)::Float64
if isempty(password)
return 0.0
end
# Detectar el pool de caracteres usado
has_lowercase = any(c -> islowercase(c), password)
has_uppercase = any(c -> isuppercase(c), password)
has_digits = any(c -> isdigit(c), password)
has_special = any(c -> !isalnum(c) && !isspace(c), password)
# Calcular tamaño del pool
pool_size = 0
pool_size += has_lowercase ? 26 : 0
pool_size += has_uppercase ? 26 : 0
pool_size += has_digits ? 10 : 0
pool_size += has_special ? 32 : 0
# Fórmula de Shannon
entropy = length(password) * log2(pool_size)
return entropy
end
密码生成器
function generate_password(;
length::Int=16,
use_lowercase::Bool=true,
use_uppercase::Bool=true,
use_digits::Bool=true,
use_special::Bool=true
)::String
charset = Char[]
use_lowercase && append!(charset, LOWERCASE)
use_uppercase && append!(charset, UPPERCASE)
use_digits && append!(charset, DIGITS)
use_special && append!(charset, SPECIAL)
# Generación criptográficamente segura
password = String([rand(charset) for _ in 1:length])
return password
end
密钥派生 (PBKDF2)
function derive_key(master_password::String, salt::Vector{UInt8}, iterations::Int=100_000)::Vector{UInt8}
# Aquí iría la llamada a una implementación de PBKDF2, por ejemplo usando
# Crypto.jl o Nettle.jl. En el demo se muestra la estructura básica.
# key = pbkdf2_hmac_sha256(master_password, salt, iterations, 32)
# return key
end
(管理器的其余代码、加密 JSON 处理、CLI 与测试,已在项目仓库中提供。)