openssl passwd -6 -salt "abc123" "mypassword" 可生成符合 /etc/shadow 格式的 SHA-512 哈希,输出形如 $6$abc123$KQV.../,需配合 chpasswd -e 或安全编辑 shadow 文件使用。

直接用 openssl passwd 生成符合 /etc/shadow 格式的哈希值
Linux 的 /etc/shadow 不接受明文密码,也不接受任意哈希结果——它要求使用特定算法(如 sha512)+ 盐(salt)+ 严格格式($6$salt$hash)。系统工具 openssl passwd 就是为此设计的,且默认行为兼容 shadow 文件解析逻辑。
实操建议:
- 用
openssl passwd -6 -salt "abc123" "mypassword"生成sha512哈希(-6表示 SHA-512,-salt指定盐值,必须为 2–16 字符、只含 [a-zA-Z0-9./]) - 不加
-salt时 openssl 会自动生成随机盐,但脚本中需捕获输出,无法复现;自动化场景务必显式指定盐 - 避免用
-1(MD5)或-5(SHA-256),前者已被弃用,后者在部分旧系统上不被login进程识别 - 输出形如
$6$abc123$KQV.../,可直接赋值给 shadow 第二字段(密码字段)
不要用 echo | sha512sum 或其他通用哈希命令
这类命令输出的是原始哈希值(如 8a7...e4f -),不含盐、无前缀、无 Base64 编码,getspnam() 等系统调用完全无法识别,写入后会导致该用户无法登录,且不会报错——只会静默失败。
常见错误现象:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 手动拼接
$6$salt$+sha512sum结果 → 登录时提示Authentication failure,auth.log中可能只有PAM: Authentication failure,无具体原因 - 用 Python
hashlib.sha512(b"pwd").hexdigest()→ 输出 128 字符十六进制串,不是 shadow 所需的 base64-encoded digest(长度、字符集、分段方式全错) - 误以为 salt 是“加在密码前面再哈希”→ 实际是 PBKDF2-like 多轮迭代过程,必须由
crypt(3)或封装它的工具执行
写入 /etc/shadow 必须绕过 passwd 命令的交互限制
passwd 命令本身不接受密码参数(出于安全强制交互),脚本中不能用 echo "pwd" | passwd user —— 它会拒绝 stdin 输入,或触发 PAM 拒绝策略。
安全可行的做法只有两种:
- 用
chpasswd -e:先用openssl passwd生成哈希,再执行echo "username:$6$salt$hash" | chpasswd -e(-e表示密码已是加密态) - 直接编辑
/etc/shadow:需 root 权限 + 正确锁机制(pwconv配合vipw -s不实用;推荐sed -i或perl -i替换对应行,但必须确保整行格式合法,字段数正确(9 个:分隔字段) - 注意:修改前务必备份原文件(
cp /etc/shadow /etc/shadow.bak),否则一行写错可能导致所有用户无法登录
脚本中处理盐值和哈希时的典型坑
盐值看似简单,但实际约束多,容易导致哈希无效:
- 盐中含
+、=、_等字符 →openssl passwd会静默截断或报错,只接受[a-zA-Z0-9./] - 盐长于 16 字符 → openssl 截取前 16 位,但不同版本行为不一致,应严格限制在 2–16 字符
- 用变量传参时未加引号:
openssl passwd -6 -salt $SALT $PASSWD若$SALT含空格会崩,必须写成"$SALT"和"$PASSWD" - 哈希值末尾含换行符 →
$(openssl ...)会带\n,写入 shadow 后破坏字段结构,建议用printf '%s' "$(openssl ...)"或tr -d '\n'
真正难的不是生成哈希,而是让整个链条每一步都满足 shadow 解析器对格式、字符集、长度的隐式约定——少一个 $,多一个空格,就等于锁死了用户账户。

















