银河麒麟V11服务器操作系统系统日志国密算法完整性保护方案
银河麒麟高级服务器操作系统V11中,通过保障特定程序日志完整性,核心是构建的全链路可信机制。
银河麒麟高级服务器操作系统V11中,通过国密算法(SM3 哈希 + SM2 非对称签名) 保障特定程序日志完整性,核心是构建 "日志生成 - 签名 - 存储 - 校验 - 审计" 的全链路可信机制。
一、密码应用基础准备
采用 SM2 非对称密钥 进行日志签名(私钥签名,公钥验签),需要注意,该方案中用到的是公钥,而不是公钥证书。
#生成SM2私钥,此步骤非必须,可以从外部导入
openssl ecparam -genkey -name SM2 -out /etc/rsyslog.d/sm2-private.pem -param_enc explicit
#生成公钥
openssl ec -in /etc/rsyslog.d/sm2-private.pem -pubout -out /etc/rsyslog.d/sm2-public.pem
# 设置权限(私钥600,公钥644)
chmod 600 /etc/rsyslog.d/sm2-private.pem
chmod 644 /etc/rsyslog.d/sm2-public.pem

二、核心配置:rsyslog 国密签名日志
通过 rsyslog 的 omprog 模块调用自定义脚本,对每条日志先计算 SM3 哈希值(防篡改核心),再用 SM2 私钥签名,最终输出带 日志内容|SM3哈希|SM2签名 的结构化日志。
(1)编写国密签名脚本
创建 /usr/local/bin/syslog-sm-sign.sh,实现 SM3 哈希 + SM2 签名逻辑:
|
#!/bin/bash set -eo pipefail # 配置路径 SM2_PRIVATE_KEY="/etc/rsyslog.d/sm2-private.pem" OUTPUT_LOG="/var/log/sm-sign.log" ERROR_LOG="/var/log/syslog-sign-error.log" # 检查私钥文件 if [ ! -f "$SM2_PRIVATE_KEY" ]; then echo "$(date) ERROR: SM2 私钥不存在 $SM2_PRIVATE_KEY" >> "$ERROR_LOG" exit 1 fi # 检查 openssl 可执行 if [ ! -x /usr/bin/openssl ]; then echo "$(date) ERROR: openssl 不可用" >> "$ERROR_LOG" exit 1 fi # 核心:稳定读取 rsyslog 日志流(解决断行、丢行) while IFS= read -r log_line || [ -n "$log_line" ]; do # 跳过空行 [ -z "$log_line" ] && continue # 计算 SM3 哈希(无换行、无格式干扰) sm3_hash=$(printf "%s" "$log_line" | openssl dgst -sm3 -binary | base64 -w 0 2>>"$ERROR_LOG") # 计算 SM2 国密签名(无换行、二进制→base64) sm2_sig=$(printf "%s" "$log_line" | openssl dgst -sm3 \ -sign "$SM2_PRIVATE_KEY" \ -keyform PEM \ -binary 2>>"$ERROR_LOG" | base64 -w 0) # 输出:严格单行,不添加任何多余换行符 printf "%s |SM3:%s |SM2:%s\n" "$log_line" "$sm3_hash" "$sm2_sig" done >> "$OUTPUT_LOG" 2>>"$ERROR_LOG" |
dos2unix /usr/local/bin/syslog-sm-sign.sh
chmod +x /usr/local/bin/syslog-sm-sign.sh

(2)修改 rsyslog 配置
编辑 /etc/rsyslog.d/sm-sign.conf,添加国密签名规则(建议单独配置安全日志,如 /var/log/secure-sm.log):
|
# 1. 加载外部命令模块 module(load="omprog") # 2. 定义日志模板:严格单行,无多余换行 template(name="SecureLogTemplate" type="string" string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %PROGRAMNAME% %MSG%\n") # 3. 匹配进程和安全级别的日志,调用签名脚本 if $programname == 'kylin_kms_daemon' or $syslogfacility-text == 'authpriv' or $syslogfacility-text == 'local6' then action( type="omprog" binary="/usr/local/bin/syslog-sm-sign.sh" template="SecureLogTemplate" ) # 4. 处理完成后停止,不进入其他规则 *.* stop |
(3)重启服务并验证
dos2unix /etc/rsyslog.d/sm-sign.conf
#检查rsyslog配置没问题
rsyslogd -N1
# 重启 rsyslog
systemctl restart rsyslog
# 发送测试日志
logger -p local6.info "Test secure log with SM3/SM2"
# 查看签名日志
验证结果示例:
2026-05-01T20:45:35.623240+08:00 localhost kylin_kms_daemon 无法将url解析为ip,请检查url是否可访问|SM3:xxxxxxxxxxxxxxxx |SM2:yyyyyyyyyyyyyyyyyy
2026-05-01T20:46:47.561792+08:00 localhost root Test secure log with SM3/SM2 |SM3:xxxxxxxxxxxxxxxx |SM2:yyyyyyyyyyyyyyyyyy
三、日志校验
创建 /usr/local/bin/syslog-sm-verify.sh,用于验证日志完整性:
|
#!/bin/bash # 国密验签脚本 SM2_PUBLIC_CRT="/etc/rsyslog.d/sm2-public.pem" LOG_FILE="/var/log/sm-sign.log" #LOG_FILE=$1 [ ! -f "$LOG_FILE" ] && echo "Log file not exist!" && exit 1 [ ! -f "$SM2_PUBLIC_CRT" ] && echo "SM2公钥证书文件不存在: $SM2_PUBLIC_CRT" && exit 1 while read -r line; do # 跳过空行 [ -z "$line" ] && continue
# 使用空格作为分隔符解析日志行:日志内容 |SM3:哈希值 |SM2:签名值 log_content=$(echo "$line" | sed 's/ |SM3:.*//') sm3_field=$(echo "$line" | grep -o '|SM3:[^ |]*') sm2_field=$(echo "$line" | grep -o '|SM2:[^ |]*')
# 检查是否包含完整的签名信息 if [ -z "$sm3_field" ] || [ -z "$sm2_field" ]; then echo "跳过不完整的日志行: $line" continue fi
# 提取哈希和签名值 sm3_hash=${sm3_field#|SM3:} sm2_sig=${sm2_field#|SM2:}
# 检查签名值是否为空 if [ -z "$sm2_sig" ]; then echo "SM2签名值为空,跳过: $log_content" continue fi
echo "content=[$log_content]"
# 1. 验证 SM3 哈希一致性 calc_sm3=$(echo -n "$log_content" | openssl dgst -sm3 -binary | base64) if [ "$calc_sm3" != "$sm3_hash" ]; then echo " SM3 校验失败: $log_content" exit 1 fi # 2. 验证 SM2 签名有效性 # 先检查base64解码是否成功 if ! echo "$sm2_sig" | base64 -d > /dev/null 2>&1; then echo "SM2签名Base64格式错误: $log_content" exit 1 fi
echo -n "$log_content" | openssl dgst -sm3 -verify "$SM2_PUBLIC_CRT" -signature <(echo "$sm2_sig" | base64 -d) if [ $? -ne 0 ]; then echo " SM2 验签失败: $log_content" exit 1 fi echo "验签成功" done < "$LOG_FILE" echo "所有日志验签成功!" |

dos2unix /usr/local/bin/syslog-sm-verify.sh
chmod +x /usr/local/bin/syslog-sm-verify.sh
# 校验签名日志
/usr/local/bin/syslog-sm-verify.sh
创建 /usr/local/bin/syslog-sm-verify-rt.sh,用于验证日志完整性:
|
#!/bin/bash # 国密实时验签脚本 SM2_PUBLIC_CRT="/etc/rsyslog.d/sm2-public.pem" LOG_FILE="/var/log/sm-sign.log" #LOG_FILE=$1 [ ! -f "$LOG_FILE" ] && echo "Log file not exist!" && exit 1 [ ! -f "$SM2_PUBLIC_CRT" ] && echo "SM2公钥证书文件不存在: $SM2_PUBLIC_CRT" && exit 1 echo "实时验签已启动,监听日志:$LOG_FILE" echo "========================================" # 核心:实时跟踪日志(tail -f 持续读) tail -n 0 -F "$LOG_FILE" | while read -r line; do # 跳过空行 [ -z "$line" ] && continue # 拆分日志内容、SM3、SM2 log_content=$(echo "$line" | sed 's/ |SM3:.*//') sm3_field=$(echo "$line" | grep -o '|SM3:[^ |]*') sm2_field=$(echo "$line" | grep -o '|SM2:[^ |]*') if [ -z "$sm3_field" ] || [ -z "$sm2_field" ]; then echo "跳过不完整的日志行: $line" continue fi sm3_hash=${sm3_field#|SM3:} sm2_sig=${sm2_field#|SM2:} # 1. 验证 SM3 哈希一致性 calc_sm3=$(printf "%s" "$log_content" | openssl dgst -sm3 -binary | base64 -w 0) if [ "$calc_sm3" != "$sm3_hash" ]; then echo "SM3 校验失败: $log_content" continue fi # 2. 验证 SM2 签名有效性 if ! echo "$sm2_sig" | base64 -d > /dev/null 2>&1; then echo " SM2签名Base64格式错误: $log_content" continue fi if ! printf "%s" "$log_content" | openssl dgst -sm3 \ -verify "$SM2_PUBLIC_CRT" \ -signature <(echo "$sm2_sig" | base64 -d); then echo " SM2 验签失败: $log_content" continue fi # 验签通过 echo "验签成功: $log_content" done |
赋予执行权限并验证:
dos2unix /usr/local/bin/syslog-sm-verify-rt.sh
chmod +x /usr/local/bin/syslog-sm-verify-rt.sh
# 校验签名日志
/usr/local/bin/syslog-sm-verify-rt.sh

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)