使用 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
文档信息
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)