Linux系统采用单向加密机制保护用户密码,即使获取加密后的密码串也无法逆向获取原始密码。核心组件包括:
#include
struct spwd *getspnam(const char *name);
返回的spwd结构体:
struct spwd {
char *sp_namp; // 用户名
char *sp_pwdp; // 加密后的密码
long sp_lstchg; // 上次修改日期
long sp_min; // 最小天数
long sp_max; // 最大天数
// ... 其他字段
};
注意:访问/etc/shadow需要root权限,普通程序应使用身份验证API而非直接读取
#include
char *getpass(const char *prompt);
安全特性:
#include
char *crypt(const char *key, const char *salt);
salt参数格式:
$id$salt$encrypted
ID | 算法 |
---|---|
1 | MD5 |
2a | Blowfish |
5 | SHA-256 |
6 | SHA-512 |
密码验证过程涉及四个主要环节:用户输入处理、权限验证、密码加密和结果比对。
用户提交凭证后,应用程序通过系统库函数getpass()安全获取密码输入。该函数会禁用回显并直接读取终端输入。
权限检查阶段,应用程序尝试获取存储在/etc/shadow中的密码哈希。普通用户无权限直接读取该文件,需通过getspnam()间接获取,该函数会根据调用方权限返回不同结果。
加密环节使用crypt()函数,该函数接受用户输入的明文密码和系统存储的salt值,采用DES/MD5/SHA等算法生成加密字符串。
最终通过逐字符比对加密结果完成验证。整个过程确保明文密码不会以任何形式存储在内存或日志中。
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s \n" , argv[0]);
return 1;
}
// 获取用户输入密码
char *password = getpass("Enter password: ");
// 获取shadow条目
struct spwd *shadow_entry = getspnam(argv[1]);
if (!shadow_entry) {
perror("getspnam");
return 1;
}
// 加密用户输入
char *encrypted = crypt(password, shadow_entry->sp_pwdp);
if (!encrypted) {
perror("crypt");
return 1;
}
// 比较加密结果
int auth_ok = strcmp(encrypted, shadow_entry->sp_pwdp) == 0;
if (auth_ok) {
printf("Authentication successful!\n");
} else {
printf("Authentication failed!\n");
}
// 安全清除内存
explicit_bzero(password, strlen(password));
return auth_ok ? 0 : 1;
}
# 编译(需要root权限访问shadow)
gcc auth_demo.c -o auth_demo -lcrypt
# 运行(需要sudo)
sudo ./auth_demo root
编辑/etc/login.defs:
ENCRYPT_METHOD SHA512 # 使用SHA-512算法
SHA_CRYPT_MIN_ROUNDS 5000 # 最小迭代次数
# 设置密码有效期
chage -M 60 -W 7 username
# 查看密码策略
chage -l username
explicit_bzero
清除敏感内存mlock()
防止内存交换# 生成SSH密钥
ssh-keygen -t ed25519
# 复制公钥到服务器
ssh-copy-id user@host
getspnam返回NULL
id username
密码不匹配但输入正确
性能优化
// 使用crypt_r可重入版本
char *crypt_r(const char *key, const char *salt,
struct crypt_data *data);
安全警告:直接访问/etc/shadow存在安全风险,生产环境应使用PAM API进行认证操作。完整示例代码参考Linux系统编程安全认证示例
本指南深入解析了Linux密码校验的核心机制,从底层加密原理到实际编程实现,帮助开发者构建更安全的认证系统。