feat(agent): Basic Auth 改为纯 Go apr1 并去掉 VPS openssl 依赖
- 新增 internal/agent/apr1.go(Apache apr_md5_encode 移植)+ 参考向量单元测试(与 openssl 输出逐字节一致) - ensureBasicAuthSecret / writeBasicAuthSecret 不再调用 openssl passwd -apr1 - 安装脚本 token 改用 /dev/urandom(内嵌副本与 scripts/agent-install.sh 同步) - AgentVersion 0.9.2;重编 amd64/arm64 内嵌二进制 - CHANGELOG v1.2.0 补记该改动
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package agent
|
||||
|
||||
import "testing"
|
||||
|
||||
// 参考向量由本机 OpenSSL 3.5.4 生成:
|
||||
//
|
||||
// openssl passwd -apr1 -salt <salt> <password>
|
||||
//
|
||||
// 自研哈希必须与 openssl 完全一致,否则 Nginx Basic Auth 会永远认证失败。
|
||||
func TestApr1CryptMatchesOpenSSLVectors(t *testing.T) {
|
||||
cases := []struct {
|
||||
password string
|
||||
salt string
|
||||
want string
|
||||
}{
|
||||
{"password", "xxxxxxxx", "$apr1$xxxxxxxx$dxHfLAsjHkDRmG83UXe8K0"},
|
||||
{"hello", "01234567", "$apr1$01234567$JGzOENmOOkvGYFfJQyG9X/"},
|
||||
{"P@ssw0rd!", "abcdefgh", "$apr1$abcdefgh$T9Ta7XuM2Yltpi/4uviFw0"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := apr1CryptWithSalt(c.password, c.salt); got != c.want {
|
||||
t.Errorf("apr1CryptWithSalt(%q, %q)\n got: %s\nwant: %s", c.password, c.salt, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApr1CryptSaltHandling(t *testing.T) {
|
||||
// 超过 8 字符的盐只取前 8 位(与 openssl / apr 行为一致)
|
||||
long := apr1CryptWithSalt("password", "xxxxxxxxyyyy")
|
||||
short := apr1CryptWithSalt("password", "xxxxxxxx")
|
||||
if long != short {
|
||||
t.Errorf("盐应截断到 8 字符: %s vs %s", long, short)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApr1CryptRandomSalt(t *testing.T) {
|
||||
first, err := apr1Crypt("password")
|
||||
if err != nil {
|
||||
t.Fatalf("apr1Crypt 失败: %v", err)
|
||||
}
|
||||
second, err := apr1Crypt("password")
|
||||
if err != nil {
|
||||
t.Fatalf("apr1Crypt 失败: %v", err)
|
||||
}
|
||||
if first == second {
|
||||
t.Error("随机盐应产生不同哈希")
|
||||
}
|
||||
// 结构:$apr1$<8 位盐>$<22 位编码> = 37 字符
|
||||
if len(first) != 37 {
|
||||
t.Errorf("哈希长度应为 37,实际 %d: %s", len(first), first)
|
||||
}
|
||||
if first[:6] != "$apr1$" || first[14] != '$' {
|
||||
t.Errorf("哈希结构异常: %s", first)
|
||||
}
|
||||
if same := apr1CryptWithSalt("password", first[6:14]); same != first {
|
||||
t.Errorf("从哈希中取出的盐应能复现同一哈希: %s vs %s", same, first)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user