如何对git项目中的文件进行加密


如何对git项目中的文件进行加密

需求

日常工作我都是用markdown来记录,然后通过git上传到公司的gitlab的某个仓库进行存储。这就带来一个问题,虽然这个gitlab仓库中成员看似只有我一个人,但gitlab管理员对所有仓库有权限,这样就不太好玩了。

于是我就想当我push时,能够对所有的markdown文件进行加密;然后我pull时,对其中加密的markdown进行解密(因为可能有一些历史文件没有加密,或者有些文件是直接在gitlab页面上添加进去的等等情况)。

实现

实现过程其实很简单,通过Git过滤器就可以实现。

STEP 1,我们先通过GPG生成一对公私钥:

gpg --full-generate-key

查找刚才生成的公私钥的ID:

gpg --list-keys

STEP 2,我们分别编写一个加密脚本和解密脚本。

加密脚本:

#!/usr/bin/env bash

# 临时文件用于保存stdin的内容
temp_file=$(mktemp)

# 从stdin读取内容并保存到临时文件
cat > "$temp_file"

# 检查文件是否为空或大小为0
if [ -s "$temp_file" ]; then
    # 文件非空,执行加密
    gpg --yes --batch --encrypt --recipient '密钥ID' < "$temp_file"
else
    # 文件为空,直接将空内容输出
    cat "$temp_file"
fi

# 清理临时文件
rm "$temp_file"

解密脚本:

#!/usr/bin/env bash

# 临时文件用于保存输入流
temp_file=$(mktemp)

# 保存标准输入到临时文件
cat > "$temp_file"

# 检查是否为GPG加密文件
if gpg --quiet --batch --list-packets "$temp_file" &> /dev/null; then
    # 是GPG加密文件,进行解密
    gpg --quiet --batch --decrypt "$temp_file"
else
    # 不是加密文件,直接输出原内容
    cat "$temp_file"
fi

# 清理临时文件
rm "$temp_file"

从这个加解密脚本也可以看出,其实加解密过程也并不是一定得用GPG,完全可以自定义。

STEP 3,为Git仓库根目录配置过滤器

git config filter.crypt.clean "path/to/scripts/encrypt.sh"
git config filter.crypt.smudge "path/to/scripts/decrypt.sh"

STEP 4,配置哪些文件需要经过上述的过滤器

在Git仓库根目录下新增/编辑.gitattributes文件,内容类似:

*.md filter=crypt

这样就实现了当push时自动加密,pull时解密:

其他注意事项

密钥备份

我这里因为采用GPG生成的公私钥作为密钥,为了防止密钥丢失,那么可以考虑将密钥导出后保存,下次万一丢失后就知道导入即可。

# 备份私钥
gpg --export-secret-keys 你的密钥ID > 私钥备份文件名.gpg

# 备份公钥
gpg --export 你的密钥ID > 公钥备份文件名.gpg

# 恢复私钥
gpg --import 私钥备份文件名.gpg

# 恢复公钥
gpg --import 公钥备份文件名.gpg

将本地所有文件全部加密

因为我本地已经有不少文档了,因此需要全部加密一下。很简单,只要将这些文档全部标记为modified即可:

find . -type f -name "*.md" -exec touch {} +