Files
idsync/internal/password/password_test.go
T
caowangrenbo 947b1a1475 chore: 初始化 idsync 项目
飞书通讯录 ↔ LDAP 同步工具的首个提交。

- internal/feishu: 飞书通讯录客户端、快照与重试
- internal/ldaplib: LDAP 读写与批量操作
- internal/mapping: 飞书部门/用户到 LDAP 条目的映射
- internal/syncer: 同步计划生成、执行与调度
- internal/store: SQLite 台账
- internal/server + internal/webui: 管理后台与内嵌前端产物
- internal/password: SSHA 口令处理
- config.example.yml / Dockerfile / Makefile / web 前端源码

真实凭据(config.yml)、运行时数据(data/、backup/)与构建产物(bin/)不入库。
2026-09-29 00:10:59 +08:00

91 lines
2.1 KiB
Go

package password
import (
"strings"
"testing"
)
func TestEncodeSSHA(t *testing.T) {
const plain = "correct horse battery staple"
encoded, err := EncodeSSHA(plain)
if err != nil {
t.Fatalf("编码失败: %v", err)
}
if !strings.HasPrefix(encoded, "{SSHA}") {
t.Errorf("结果应以 {SSHA} 开头,实际: %q", encoded)
}
// 关键性质:明文绝不能出现在结果里。
// slapd 不会自动哈希 Modify 写入的 userPassword,因此这一步是
// 密码不落明文存储的唯一保障。
if strings.Contains(encoded, plain) {
t.Errorf("编码结果中出现了明文密码: %q", encoded)
}
if !VerifySSHA(encoded, plain) {
t.Errorf("正确密码校验失败: %q", encoded)
}
if VerifySSHA(encoded, plain+"x") {
t.Errorf("错误密码不应通过校验")
}
}
func TestEncodeSSHASaltIsRandom(t *testing.T) {
const plain = "same-password"
a, err := EncodeSSHA(plain)
if err != nil {
t.Fatalf("编码失败: %v", err)
}
b, err := EncodeSSHA(plain)
if err != nil {
t.Fatalf("编码失败: %v", err)
}
// 随机盐应让同一密码产生不同哈希,避免相同密码在目录中可被关联识别。
if a == b {
t.Errorf("同一密码两次编码结果相同,说明盐未随机化: %q", a)
}
if !VerifySSHA(a, plain) || !VerifySSHA(b, plain) {
t.Errorf("带随机盐的两个哈希都应能校验通过")
}
}
func TestVerifySSHARejectsMalformed(t *testing.T) {
cases := []struct {
name string
encoded string
}{
{"空字符串", ""},
{"缺少前缀", "abcdef"},
{"前缀但非法 base64", "{SSHA}!!!not-base64!!!"},
{"长度不足以容纳哈希", "{SSHA}YWJj"},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
if VerifySSHA(c.encoded, "whatever") {
t.Errorf("畸形输入 %q 不应校验通过", c.encoded)
}
})
}
}
func TestRandom(t *testing.T) {
a, err := Random()
if err != nil {
t.Fatalf("生成失败: %v", err)
}
b, err := Random()
if err != nil {
t.Fatalf("生成失败: %v", err)
}
if a == b {
t.Errorf("两次生成的随机密码相同: %q", a)
}
if len(a) < 20 {
t.Errorf("随机密码过短(%d 字符),强度不足", len(a))
}
}