银河麒麟高级服务器操作系统V11中,通过国密算法(SM3 哈希 + SM2 非对称签名) 保障特定程序日志完整性,核心是构建 "日志生成 - 签名 - 存储 - 校验 - 审计" 的全链路可信机制。

一、密码应用基础准备

  1. 国密密钥与证书生成

采用 SM2 非对称密钥 进行日志签名(私钥签名,公钥验签),需要注意,该方案中用到的是公钥,而不是公钥证书。

  1. 私钥权限严格控制(仅 root 可读),避免泄露。
  2. 证书建议由企业内部 CA 签发,或使用自签证书(测试环境)。

#生成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 国密签名日志

  1. 配置原理

通过 rsyslog 的 omprog 模块调用自定义脚本,对每条日志先计算 SM3 哈希值(防篡改核心),再用 SM2 私钥签名,最终输出带 日志内容|SM3哈希|SM2签名 的结构化日志。

  1. 分步配置
(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"

# 查看签名日志

cat /var/log/sm-sing.log

验证结果示例:

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

三、日志校验

  1. 国密验签脚本(一次性)

创建 /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

  1. 国密验签脚本(实时)

创建 /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

Logo

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

更多推荐