openssl passwd -crypt支持符号及密码加密问题与替代方案咨询
openssl passwd -crypt的字符支持与脚本问题解析 首先得明确:你遇到的密码解析问题根本不是openssl passwd -crypt的锅,而是bash shell对特殊字符的处理规则导致的!下面一步步给你拆解:
一、为什么$、!、#会出问题?
这些字符在bash里自带特殊含义,你的脚本没做处理的话,shell会先把它们解析掉,再传给openssl:
$:用来引用变量(比如$PATH),如果密码里有$abc,shell会尝试找名为abc的变量,把它替换成变量值,导致原密码被篡改。!:历史命令扩展符,在默认配置下,bash会把!开头的内容替换成之前执行过的命令,直接打乱你的密码。#:注释符号,一旦遇到#,shell会忽略后面所有内容,你的密码会被截断。
而+能正常工作,是因为它在bash的双引号里没有特殊含义,能原封不动传递给openssl。
二、openssl passwd -crypt本身支持哪些字符?
其实它对密码字符没有任何限制——只要你能让shell把原始密码完整传递给它,任何ASCII字符(包括你提到的$、!、#)都可以正常加密。
三、修复你的bash脚本
核心思路是让shell不对密码里的特殊字符做解析,推荐两种最可靠的方式:
1. 用单引号包裹密码(推荐)
单引号在bash里会完全禁用特殊字符解析,是最安全的做法:
# 密码用单引号包裹,确保所有字符都被原样保留 MYPASS='$tr!ng#with$pec!als' # 加密时用双引号包裹变量,避免空格等字符被拆分 CRYPTPASS="$(openssl passwd -crypt "$MYPASS")" # 给usermod传参时也要用双引号,防止加密后的密码里的特殊字符被shell解析 sudo usermod -p "$CRYPTPASS" newUsername
2. 转义特殊字符
如果必须用双引号,需要对$、!、#等特殊字符加反斜杠\转义:
MYPASS="\$tr\!ng\#with\$pec\!als" CRYPTPASS="$(openssl passwd -crypt "$MYPASS")" sudo usermod -p "$CRYPTPASS" newUsername
四、更安全且支持全字符的加密替代方案
-crypt用的是老旧的DES加密,不仅强度弱,很多现代Linux发行版已经默认不推荐使用了。推荐这些更优的方案:
1. SHA-512加密(系统标准)
用openssl passwd -6生成SHA-512哈希(这是当前Linux用户密码的默认加密方式),支持所有字符,用法和-crypt一致:
MYPASS='$tr!ng#with$pec!als' CRYPTPASS="$(openssl passwd -6 "$MYPASS")" sudo usermod -p "$CRYPTPASS" newUsername
2. 使用mkpasswd命令
如果系统安装了whois包(大部分发行版可以通过apt install whois或yum install whois安装),mkpasswd可以更便捷生成加密密码,默认就是SHA-512:
CRYPTPASS="$(mkpasswd -m sha-512 '$tr!ng#with$pec!als')" sudo usermod -p "$CRYPTPASS" newUsername
3. chpasswd批量设置(更安全)
如果是批量创建用户,推荐用chpasswd,它从标准输入读取用户名和密码,避免密码在命令行暴露(命令行历史会记录明文密码,这很危险):
# -e表示输入的是加密后的密码,如果是明文就去掉-e echo "newUsername:$CRYPTPASS" | sudo chpasswd -e # 明文密码直接传: # echo "newUsername:$tr!ng#with$pec!als" | sudo chpasswd
最后提醒
永远不要在脚本里硬编码明文密码!如果需要自动生成密码,推荐用openssl rand生成安全的随机密码:
# 生成12位随机密码(base64格式,包含大小写、数字、符号) MYPASS="$(openssl rand -base64 12)"
内容的提问来源于stack exchange,提问作者sdexp

