gpg 加密脚本

使用 GPG 对给定的文件进行加密(不支持文件夹加密)

1. 使用帮助

./encrypt.sh -h

2. 加密脚本

#!/bin/bash
###############################################################################
# GPG Ultimate Security Workflow v2.0
###############################################################################
#
# 作者: Jeffrey Guan
# 邮箱: double12gzh@gmail.com
# 创建日期: 2024-03-24
# 最后更新: 2024-03-24
# GitHub: https://github.com/double12gzh
#
# 功能描述:
#   - 高强度 GPG 密钥生成和管理
#   - 文件加密与解密
#   - 密钥备份与恢复
#   - 跨设备密钥迁移
#   - 密钥安全性检查
#   - 密钥轮换管理
#
# 安全特性:
#   - 使用 RSA-4096 或 ED25519 密钥
#   - AES-256 对称加密
#   - SHA-512 哈希算法
#   - 内存安全处理
#   - 自动密钥备份
#   - 安全参数配置
#
# 依赖:
#   - GnuPG 2.2+
#   - Bash 4.0+
#
# 环境要求:
#   - Linux/macOS
#   - 足够的系统内存(推荐 4GB 以上)
#
# 注意事项:
#   1. 请妥善保管生成的密钥和密码
#   2. 建议定期进行密钥更新
#   3. 重要文件建议使用多重加密
#   4. 系统重启后内存数据会被清除
#
# 更新历史:
#   v1.0 (2024-03-24)
#   - 添加密钥安全检查功能
#   - 优化内存处理机制
#   - 增强跨平台兼容性
#
# 许可证:
#   MIT License
#   Copyright (c) 2024 Jeffrey Guan
#
###############################################################################

set -euo pipefail

GREEN='\033[0;32m'
RED='\033[0;31m'
GRAY='\033[1;34m'
NC='\033[0m' # No Color

ERR_LOG='error.log'
temp_dir=""  # 临时目录,用于存放密钥(保存在内存中)

cleanup() {
    echo -e "\n\n${GRAY}Performing secure cleanup...${NC}"
    # 删除临时目录,但保留加密后的主子密钥文件
    rm -rf "$temp_dir"
}

# 设置 trap,捕获 EXIT 和 ERR 信号
trap 'cleanup; if [[ $? -ne 0 ]]; then echo -e "${RED}Operation failed!${NC}"; exit 1; fi' EXIT ERR

usage() {
    echo "Usage: $0 <encrypt|decrypt|check> [options]"
    echo -e "  ${GREEN}encrypt        ${GRAY}<file_to_encrypt>${NC}                      Encrypt a file"
    echo -e "  ${GREEN}decrypt        ${GRAY}<file_to_decrypt> <private_key>${NC}        Decrypt a file using a private key"
    echo -e "  ${GREEN}check          ${GRAY}<key_file>${NC}                             Check private key details"
    exit 1
}

if [ $# -lt 1 ]; then
    usage
fi

command="$1"
shift

# 创建一个内存临时目录,用于存放密钥
if [ -d "/dev/shm" ]; then
    temp_dir=$(mktemp -d -p /dev/shm)
else
    temp_dir=$(mktemp -d)
fi

export GNUPGHOME="$temp_dir"

decrypt_key() {
    encrypted_private_key="$1"  # 加密的私钥文件路径
    read -s -p "Enter passphrase to decrypt the private key: " key_decryption_passphrase
    echo

    # 解密密钥并导入内存
    gpg --batch --yes --passphrase "$key_decryption_passphrase" --decrypt --output $temp_dir/decrypted_master.asc "$encrypted_private_key"
    gpg --batch --yes --passphrase "$key_decryption_passphrase" --decrypt --output $temp_dir/decrypted_sub.asc "$encrypted_private_key"

    # 导入解密的私钥到内存
    gpg --import $temp_dir/decrypted_master.asc
    gpg --import $temp_dir/decrypted_sub.asc

    # 删除临时解密密钥
    rm -f $temp_dir/decrypted_master.asc
    rm -f $temp_dir/decrypted_sub.asc
}

# 添加一个跨平台的日期转换函数
format_timestamp() {
    local timestamp=$1
    if [[ "$OSTYPE" == "darwin"* ]]; then
        # macOS
        date -r "$timestamp" "+%Y-%m-%d %H:%M:%S"
    else
        # Linux
        date -d "@$timestamp" "+%Y-%m-%d %H:%M:%S"
    fi
}

case "$command" in
    encrypt)
        if [ $# -ne 1 ]; then usage; fi
        input_file="$1"
        encrypted_file="${input_file}.gpg"

        read -s -p "Enter passphrase for new key: " key_passphrase
        echo
        read -p "Enter key expiration (e.g., 1y for one year, 0 for no expiration): " key_expire

        echo "Generating GPG key..."
        cat > "$temp_dir/key_config" <<EOF
            %echo Generating ECC key pair...
            Key-Type: eddsa
            Key-Curve: ed25519
            Subkey-Type: ecdh
            Subkey-Curve: cv25519
            Name-Real: Temporary Encryption Key
            Expire-Date: $key_expire
            Passphrase: $key_passphrase
            %commit
EOF

        # 生成密钥并导出密钥
        gpg --batch --generate-key "$temp_dir/key_config" 2> $ERR_LOG
        KEY_ID=$(gpg --list-keys --with-colons | awk -F: '/^pub:/ {print $5}')

        echo "Exporting public key and encrypted master/private keys..."
        gpg --export -a "$KEY_ID" > "${input_file}.pubkey.asc"

        # 将主密钥和子密钥导出到磁盘
        gpg --export-secret-keys -a "$KEY_ID" > "${input_file}.master-private.asc"
        gpg --export-secret-subkeys -a "$KEY_ID" > "${input_file}.sub-private.asc"

        # 对导出的主子密钥进行加密
        read -s -p "Enter passphrase to encrypt the keys: " key_encryption_passphrase
        echo
        gpg --batch --yes --passphrase "$key_encryption_passphrase" --symmetric --cipher-algo AES256 --output "${input_file}.master-private.enc" "${input_file}.master-private.asc"
        gpg --batch --yes --passphrase "$key_encryption_passphrase" --symmetric --cipher-algo AES256 --output "${input_file}.sub-private.enc" "${input_file}.sub-private.asc"

        # 删除明文主子密钥文件(确保仅加密过的密钥保存在磁盘)
        rm -f "${input_file}.master-private.asc"
        rm -f "${input_file}.sub-private.asc"
        rm -f "$temp_dir/key_config"

        # 加密文件
        gpg --batch --yes --encrypt --recipient "$KEY_ID" --output "$encrypted_file" "$input_file"

        echo -e "${GREEN}Encryption successful. Keys exported as ${input_file}.pubkey.asc, ${input_file}.master-private.enc, and ${input_file}.sub-private.enc${NC}"
        ;;

    decrypt)
        if [ $# -ne 2 ]; then usage; fi
        encrypted_file="$1"
        encrypted_private_key="$2"
        decrypted_file="${encrypted_file%.gpg}.decrypted"

        # 导入加密的私钥
        decrypt_key "$encrypted_private_key"

        echo "Decrypting file..."
        gpg --batch --yes --decrypt --output "$decrypted_file" "$encrypted_file"

        echo -e "${GREEN}Decryption successful: $decrypted_file${NC}"
        ;;

    check)
        if [ $# -ne 1 ]; then usage; fi
        key_file="$1"

        # 导入并解密私钥
        decrypt_key "$key_file"

        KEY_ID=$(gpg --list-keys --with-colons | awk -F: '/^pub:/ {print $5}')
        echo "Key Details:"
        gpg --list-keys "$KEY_ID"

        expiration_date=$(gpg --list-keys --with-colons "$KEY_ID" | awk -F: '/^pub:/ {print $7}')
        if [ "$expiration_date" -gt 0 ]; then
            echo -e "${GREEN}Key Expiration Date: $(format_timestamp "$expiration_date")${NC}"
        else
            echo -e "${GREEN}Key does not expire.${NC}"
        fi
        ;;
    *)
        usage
        ;;
esac

出处

文档信息

Search

    Table of Contents