文件打包与加密传输

概述

数据在传输前需要进行打包压缩和加密处理,以确保传输效率和数据安全。本文详细介绍使用 bash 工具链实现文件打包、加密传输、分卷传输和断点续传。

核心理念

  • 先压缩后加密:提高传输效率同时保证安全
  • 完整性校验:使用校验和验证数据完整性
  • 分卷传输:大文件分块传输,支持断点续传
  • 密钥管理:安全的密钥生成和分发

1. tar + 加密打包

pack_and_encrypt() {
    local input="$1" output="$2" password="$3"
    local temp_file
    temp_file=$(mktemp /tmp/pack_XXXXXX.tar.gz)
 
    # 打包压缩
    tar czf "$temp_file" -C "$(dirname "$input")" "$(basename "$input")" 2>/dev/null
 
    # openssl 加密
    openssl enc -aes-256-cbc -salt -pbkdf2 \
        -in "$temp_file" \
        -out "$output" \
        -pass "pass:$password" 2>/dev/null
 
    local checksum
    checksum=$(sha256sum "$output" | awk '{print $1}')
    echo "$checksum" > "${output}.sha256"
    rm -f "$temp_file"
    echo "[+] 已加密: $output (SHA256: ${checksum:0:16}...)"
}
 
unpack_and_decrypt() {
    local input="$1" output_dir="$2" password="$3"
    local temp_file
    temp_file=$(mktemp /tmp/unpack_XXXXXX.tar.gz)
 
    openssl enc -aes-256-cbc -d -salt -pbkdf2 \
        -in "$input" \
        -out "$temp_file" \
        -pass "pass:$password" 2>/dev/null
 
    mkdir -p "$output_dir"
    tar xzf "$temp_file" -C "$output_dir" 2>/dev/null
    rm -f "$temp_file"
    echo "[+] 已解压到: $output_dir"
}
 
verify_integrity() {
    local file="$1"
    local checksum_file="${1}.sha256"
    [[ ! -f "$checksum_file" ]] && { echo "[-] 校验文件不存在"; return 1; }
    local expected actual
    expected=$(cat "$checksum_file")
    actual=$(sha256sum "$file" | awk '{print $1}')
    if [[ "$expected" == "$actual" ]]; then
        echo "[+] 完整性验证通过"
        return 0
    else
        echo "[-] 完整性验证失败"
        return 1
    fi
}

1.2 GPG 加密传输

gpg_encrypt() {
    local file="$1" recipient="$2" output="${1}.gpg"
    gpg --encrypt --recipient "$recipient" --output "$output" "$file"
    echo "[+] GPG 加密完成: $output"
}
 
gpg_symmetric_encrypt() {
    local file="$1" password="$2" output="${1}.gpg"
    echo "$password" | gpg --batch --yes --passphrase-fd 0 \
        --symmetric --cipher-algo AES256 \
        --output "$output" "$file"
    echo "[+] 对称加密完成: $output"
}

2. openssl 加密传输

openssl_transfer() {
    local file="$1" remote="$2" remote_path="$3" password="$4"
    echo "[*] 加密传输: $file -> $remote:$remote_path"
 
    cat "$file" | \
        openssl enc -aes-256-cbc -salt -pbkdf2 -pass "pass:$password" | \
        ssh "$remote" "cat > ${remote_path}.enc"
 
    sha256sum "$file" | ssh "$remote" "cat > ${remote_path}.sha256"
    echo "[+] 传输完成"
}
 
openssl_receive() {
    local remote="$1" remote_file="$2" local_file="$3" password="$4"
    ssh "$remote" "cat $remote_file" | \
        openssl enc -aes-256-cbc -d -salt -pbkdf2 -pass "pass:$password" > "$local_file"
    echo "[+] 接收完成: $local_file"
}
 
generate_openssl_keys() {
    local output_dir="${1:-/tmp/keys}"
    mkdir -p "$output_dir"
    openssl genrsa -out "$output_dir/private.pem" 2048 2>/dev/null
    openssl rsa -in "$output_dir/private.pem" \
        -pubout -out "$output_dir/public.pem" 2>/dev/null
    echo "[+] 密钥对已生成: $output_dir"
}

3. SCP/SFTP 安全传输

scp_transfer() {
    local file="$1" remote="$2" remote_path="$3"
    echo "[*] SCP 传输: $file -> $remote:$remote_path"
    gzip -c "$file" | ssh "$remote" "gunzip -c > ${remote_path}/$(basename "$file")"
 
    local local_md5 remote_md5
    local_md5=$(md5sum "$file" | awk '{print $1}')
    remote_md5=$(ssh "$remote" "md5sum ${remote_path}/$(basename "$file")" | awk '{print $1}')
 
    if [[ "$local_md5" == "$remote_md5" ]]; then
        echo "[+] 传输验证通过"
    else
        echo "[-] 传输验证失败"
        return 1
    fi
}
 
rsync_transfer() {
    local source="$1" remote="$2" dest="$3"
    rsync -avz --progress --partial \
        -e "ssh -o StrictHostKeyChecking=no" \
        "$source" "${remote}:${dest}"
    echo "[+] rsync 同步完成"
}
 
rsync_resume() {
    local source="$1" remote="$2" dest="$3"
    rsync -avz --progress --partial --append-verify \
        -e "ssh" \
        "$source" "${remote}:${dest}"
    echo "[+] 断点续传完成"
}

4. 压缩 + 分卷传输

split_transfer() {
    local file="$1" remote="$2" remote_path="$3"
    local chunk_size="${4:-10M}"
 
    echo "[*] 分卷传输: $file (每块 $chunk_size)"
 
    # 分卷压缩
    local split_prefix="/tmp/split_$$"
    split -b "$chunk_size" "$file" "${split_prefix}_"
 
    # 逐块传输
    for part in "${split_prefix}"_*; do
        echo "  传输: $(basename "$part")"
        scp "$part" "$remote:${remote_path}/"
    done
 
    # 远程重组
    ssh "$remote" "cat ${remote_path}/split_* > ${remote_path}/$(basename "$file")"
 
    # 清理
    rm -f "${split_prefix}"_*
    echo "[+] 分卷传输完成"
}
 
split_receive() {
    local remote="$1" remote_path="$2" local_file="$3"
    ssh "$remote" "cat ${remote_path}/*" > "$local_file"
    echo "[+] 接收完成: $local_file"
}

5. 综合传输脚本

secure_transfer() {
    local file="$1" remote="$2" remote_path="$3" password="$4"
    local method="${5:-openssl}"
 
    echo "[*] 安全传输: $file -> $remote:$remote_path (方法: $method)"
 
    case "$method" in
        openssl)
            openssl_transfer "$file" "$remote" "$remote_path" "$password"
            ;;
        scp)
            scp_transfer "$file" "$remote" "$remote_path"
            ;;
        rsync)
            rsync_transfer "$file" "$remote" "$remote_path"
            ;;
        split)
            split_transfer "$file" "$remote" "$remote_path" "${6:-10M}"
            ;;
        *)
            echo "[-] 未知方法: $method"
            return 1
            ;;
    esac
}

总结

本文介绍了使用 bash 工具链实现安全文件传输的完整方案:tar+openssl 打包加密、GPG 加密、SSH/SCP 安全传输、rsync 增量同步、分卷传输和断点续传。这些技术可以组合使用,确保数据在传输过程中的完整性和机密性。