实用脚本能批量验签吗?

wen 实用脚本 13

本文目录导读:

实用脚本能批量验签吗?

  1. 核心思路
  2. 方案一:批量验证 OpenPGP 签名(如 .asc /.sig 文件)
  3. 方案二:批量验证 HMAC-SHA256 签名(如 API 回调/文件完整性)
  4. 方案三:批量验证 JWT 签名(如 API 测试/日志分析)
  5. 方案四:使用 OpenSSL 批量验证数字签名(.sig / .p7s)
  6. 总结与建议

可以的,实用脚本完全可以实现批量验签功能。

批量验签是开发、运维和安全审计中非常常见的需求,比如验证一批下载文件的完整性、批量校验API回调的签名等。

下面提供几种常见的脚本实现方式和示例,你可以根据你的应用场景(如文件校验、API签名、JWT等)选择合适的方案。

核心思路

  1. 遍历文件或数据列表
  2. 读取签名和原始数据,签名可能存储在单独的文件(.sig)、文件末尾(如某些PGP签名)、或一个清单文件中。
  3. 执行验签命令
  4. 汇总结果

批量验证 OpenPGP 签名(如 .asc /.sig 文件)

这是验证下载的软件包(如Linux ISO、数据库驱动)最常见的情况。

场景: 你有一个文件夹,里面既有 file.zip,又有对应的 file.zip.asc,需要验证所有文件。

脚本:batch_gpg_verify.sh

#!/bin/bash
# 批量验证当前目录下所有 .zip.asc 签名文件
# 需要提前导入公钥
SIGNED_FILE_EXT=".zip.asc"
PUBLIC_KEY_FILE="./public-key.asc" # 可选,如果没有导入到keyring
echo "开始批量验签..."
# 先导入公钥(如果提供了)
if [ -f "$PUBLIC_KEY_FILE" ]; then
    echo "导入公钥..."
    gpg --import "$PUBLIC_KEY_FILE"
fi
FAIL_COUNT=0
PASS_COUNT=0
for sig_file in *"$SIGNED_FILE_EXT"; do
    # 获取原始文件名(去掉 .asc 后缀)
    original_file="${sig_file%.asc}"
    if [ ! -f "$original_file" ]; then
        echo "[跳过] 找不到原始文件: $original_file"
        continue
    fi
    echo -n "验证: $original_file ... "
    # 执行验签
    gpg --verify "$sig_file" "$original_file" 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "✅ 通过"
        PASS_COUNT=$((PASS_COUNT + 1))
    else
        echo "❌ 失败! (签名无效或公钥缺失)"
        FAIL_COUNT=$((FAIL_COUNT + 1))
    fi
done
echo ""
echo "========= 汇总 ========="
echo "通过: $PASS_COUNT"
echo "失败: $FAIL_COUNT"
exit $FAIL_COUNT

运行:

chmod +x batch_gpg_verify.sh
./batch_gpg_verify.sh

批量验证 HMAC-SHA256 签名(如 API 回调/文件完整性)

场景: 你有多个文件,以及一个包含文件名和签名的CSV文件(或计算后追加了签名)。

脚本:batch_hmac_verify.py (Python,更灵活)

假设有一个清单文件 files.csv 内容如下:

filename,expected_signature
data_1.csv,abc123def456...
data_2.csv,789ghi012jkl...
#!/usr/bin/env python3
import csv
import hmac
import hashlib
import sys
import os
# 你的密钥(请替换为实际密钥)
SECRET_KEY = b"your_secret_key_here" 
def calculate_hmac(filepath):
    """计算文件的 HMAC-SHA256"""
    h = hmac.new(SECRET_KEY, digestmod=hashlib.sha256)
    with open(filepath, 'rb') as f:
        # 对于大文件,分块读取
        while chunk := f.read(8192):
            h.update(chunk)
    return h.hexdigest()
def main():
    manifest_file = sys.argv[1]  # CSV清单文件路径
    base_dir = os.path.dirname(manifest_file) or '.'
    pass_count = 0
    fail_count = 0
    with open(manifest_file, 'r') as f:
        reader = csv.DictReader(f)
        for row in reader:
            filename = row['filename']
            expected_sig = row['expected_signature'].strip()
            filepath = os.path.join(base_dir, filename)
            if not os.path.exists(filepath):
                print(f"⚠️  文件不存在: {filename}")
                fail_count += 1
                continue
            calculated_sig = calculate_hmac(filepath)
            # 使用 hmac.compare_digest 防止计时攻击
            if hmac.compare_digest(calculated_sig, expected_sig):
                print(f"✅ {filename} 验签通过")
                pass_count += 1
            else:
                print(f"❌ {filename} 验签失败 (期望: {expected_sig[:10]}..., 计算: {calculated_sig[:10]}...)")
                fail_count += 1
    print(f"\n结果: 通过 {pass_count}, 失败 {fail_count}")
    return fail_count
if __name__ == "__main__":
    sys.exit(main())

运行:

python3 batch_hmac_verify.py files.csv

批量验证 JWT 签名(如 API 测试/日志分析)

场景: 你有一个文本文件,每行是一个JWT字符串,需要验证其签名是否有效。

脚本:batch_jwt_verify.py (使用 PyJWT)

#!/usr/bin/env python3
import jwt
import sys
# 你的验证密钥(对称算法用 secret,非对称用 public key)
SECRET = "your_256_bit_secret"  
PUBLIC_KEY = None # 如用 RS256,加载公钥
def verify_jwt(token):
    """验证单个JWT"""
    try:
        # 对于 HS256 (对称)
        decoded = jwt.decode(token, SECRET, algorithms=["HS256"])
        return True, decoded
    except jwt.ExpiredSignatureError:
        return False, "Token已过期"
    except jwt.InvalidTokenError as e:
        return False, f"无效签名: {e}"
    # 对于 RS256 (非对称)
    # decoded = jwt.decode(token, PUBLIC_KEY, algorithms=["RS256"])
def main():
    if len(sys.argv) < 2:
        print("用法: python3 batch_jwt_verify.py <tokens.txt>")
        sys.exit(1)
    input_file = sys.argv[1]
    pass_count = 0
    fail_count = 0
    with open(input_file, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            token = line.strip()
            if not token:
                continue
            is_valid, result = verify_jwt(token)
            if is_valid:
                print(f"行{line_num}: ✅ 验证通过. Payload: {result}")
                pass_count += 1
            else:
                print(f"行{line_num}: ❌ 验证失败 - {result}")
                fail_count += 1
    print(f"\n汇总: 通过 {pass_count}, 失败 {fail_count}")
    sys.exit(fail_count)
if __name__ == "__main__":
    main()

运行:

pip install pyjwt
python3 batch_jwt_verify.py collected_tokens.txt

使用 OpenSSL 批量验证数字签名(.sig / .p7s)

场景: 验证由私钥签名的文件(如软件发布签名)。

脚本:batch_openssl_verify.sh

假设签名的文件格式为 file.bin.sig (原始签名)和 file.bin

#!/bin/bash
# 批量验证 OpenSSL dgst 签名
# 签名生成时的命令: openssl dgst -sha256 -sign private.pem -out file.bin.sig file.bin
PUBLIC_KEY="public.pem"
SIG_DIR="./sigs"  # 签名文件存放目录
DATA_DIR="./data" # 原始数据存放目录
echo "使用公钥: $PUBLIC_KEY"
echo "开始批量验签..."
FAIL_COUNT=0
PASS_COUNT=0
for sig_file in "$SIG_DIR"/*.sig; do
    base_name=$(basename "$sig_file" .sig)
    data_file="$DATA_DIR/$base_name"
    if [ ! -f "$data_file" ]; then
        echo "[跳过] 找不到数据文件: $data_file"
        continue
    fi
    echo -n "验证: $base_name ... "
    openssl dgst -sha256 -verify "$PUBLIC_KEY" -signature "$sig_file" "$data_file" 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "✅"
        PASS_COUNT=$((PASS_COUNT + 1))
    else
        echo "❌"
        FAIL_COUNT=$((FAIL_COUNT + 1))
    fi
done
echo ""
echo "通过: $PASS_COUNT, 失败: $FAIL_COUNT"
exit $FAIL_COUNT

总结与建议

场景 推荐工具 速度 适用性
PGP/GPG 签名验证 Shell + gpg 软件发布包、邮件加密
HMAC/对称完整性校验 Python + hmac API签名、内部文件校验
JWT 验证 Python + pyjwt Web API测试、令牌分析
非对称签名 (OpenSSL) Shell + openssl 数字证书、软件签名
PKCS#7 / 数字信封 Shell + openssl smime Windows二进制签名

几点实用建议:

  1. 多线程/多进程:如果需要验证成千上万的文件,建议在Python脚本中引入concurrent.futures来并行处理,可以显著提升速度。
  2. 错误处理:一定要处理文件不存在、签名格式错误等情况,避免整个脚本中断。
  3. 日志输出:建议将失败的文件名和错误信息输出到另一个文件(如 verify_fail.log),方便后续排查。
  4. 密钥管理:对于HMAC场景,不要在脚本中硬编码密钥(尤其是提交到Git时),推荐使用环境变量或密钥管理服务(如KMS、Vault)。

是的,实用脚本完全可以高效地实现批量验签,根据你的具体场景(文件签名类型、性能要求、环境限制),选择上述合适的脚本方案即可,如果需要进一步定制(比如针对某种特定格式的签名),可以再提供具体细节。

抱歉,评论功能暂时关闭!