使用 age 加密
国内的通讯工具并不安全[1],尤其是微博等等工具上 404 已经成为家常便饭的时候,想要安全的和对方说一件事会变的尤为困难。在你没有办法使用国外通讯工具时,你又想给对方表达可能比较敏感的信息,那么你需要一个加密工具,避免中间人获取你想表达的信息。
本文将详细讲解使用 age 来加密数据。
关于 age
age 是 Actual Good Encryption 的缩写,是一个轻量且简单的命令行非对称加密工具,加密过程中会用到公钥和私钥。非对称加密原理是用公钥加密的信息,只能用私钥解密,通常用于通信。用私钥加密的信息,只能用公钥解密,通常用于数字签名,告知对方文件由私钥所有者本人所发出。
age 使用 Go 语言编写,并开源在 GitHub。还有一个使用 ruby 编写的版本 rage,有兴趣可以去看看。
基础知识
阅读本文前,我假定你有一定的命令行水平,至少知道打开命令行窗口,知道当前工作路径。否则,你可能需要在学习的时候依赖搜索引擎。你只要会基本操作就能照着这篇文章学会使用 age。如果你是有一定命令行使用基础的人,请直接跳转下载 age。
cmd / 终端
age 是个命令行工具,在 Windows 下需要在 cmd 里运行,macOS 则是终端。按住 Windows 键不松开再按 R 键,会弹出运行窗口,输入 cmd 点击确定,就能运行 cmd。macOS 直接搜索终端即可 (部分用户可能会使用 iTerm2 等第三方终端工具,但相信使用了的用户也不会看这一段基础知识)。
cmd 是一个黑色的窗口,>
号前面是当前工作路径,如果你需要切换当前工作路径到 age 所在的目录 (后面会用到。如果你不想一直切换,可以把 age 添加到 path ,这会省下很多时间),可以使用 cd 命令来切换 (格式为 cd + 路径)。比如你要切换到 C:\Program Files
这个目录,你就可以这么输入:
$ cd C:\Program Files
手输路径会非常麻烦,你可以点击文件夹窗口的地址栏,复制文件夹地址后粘贴。但是,cmd 默认的起始路径是在 C 盘,如果你需要去其他分区下,需要先切换盘符,再使用 cd 命令。例:我要去到 D:\Program Files
:
$ D:
$ cd D:\Program Files
先输入盘符加冒号 (冒号应该是半角,如果你开启了中文输入法,冒号将是全角,关闭之后就是半角),回车后切换盘符,然后再使用 cd 命令。
以下所有的命令前面都会有个 $
符号,这是代表着在命令行的环境下,不带 $
的就不是命令了。比如下图是 Windows 系统下的 Git Bash。
如果你电脑上已经有了 Git bash,或者你即将因为手动编译而下载安装好了 Git,那么你可以忽略 cmd 繁琐的 cd 命令,直接在你想要去的文件夹右键,会有 Git bash here。
命令行会在前面带上一个 $
符号 (虽然这个符号不起作用,也删不掉,只是提示你在命令行下),所以对着本教程的时候就不要把 $
号一起输入进来了。哪怕你在 Windows 的 cmd 下,也不要输入。
如果你是复制了教程中的命令,在 cmd (或者是 powershell) 下点击鼠标右键就能粘贴在命令行里;如果你是 Git Bash 或者其他系统的 Bash, zsh 等命令行工具,可以使用鼠标右键粘贴。
添加 path
将 age 所在的路径添加到 path 里,将可以在任意工作目录下运行 age。
如果你在 Windows,下载 age 后希望在各个工作目录都能运行 age,可以将 age 的路径添加到 PATH 里。右键计算机 (此电脑) / 在此电脑窗口里右键 → 属性 → 高级系统设置 → 环境变量 → 双击系统变量的 PATH。如果你是 Win10,新建并粘贴 age 所在的路径即可;如果你是 Win7,在后面输入一个半角分号后粘贴。添加完成后,一路点击确定来关闭。
如果你在添加 Path 的时候 cmd 是运行的,那你需要重新打开 cmd 才会使更改后的 Path 生效。 |
如果你是 macOS 等 unix 系统,在 age 的目录下,执行 pwd
命令来获取当前目录的绝对路径 (Windows cmd 下 >
符号前就是当前工作路径,但是 Git bash 的 pwd
结果不太适合直接添加到 PATH 里)。如果你在其他目录,先切换到 age 的路径再执行 pwd
命令。获取到绝对路径后 export
到 PATH
变量里。
$ pwd
/Users/epi/age
$ export PATH="$PATH:/Users/epi/age"
以上是我在私人电脑上的执行结果,可以参考示例代码来举一反三。另外 export 在你关闭终端窗口后就会失效,如果你需要它一直存在,需要将它写进 .bashrc
里 (zsh 用户是 .zshrc
)。
$ echo 'export PATH="$PATH:/Users/epi/age"' >> ~/.bashrc
$ echo 'export PATH="$PATH:/Users/epi/age"' >> ~/.zshrc
Git bash 和 cmd 的差异
Git bash 的字体会圆滑一些,而且你可以用 tab 键快速补全 (cmd 也有,bash 更优秀一些)。
cmd 要执行当前目录下的可执行文件,直接输入名字就行了,但 bash 需要加上 ./
(.
代表着当前目录,这么做是为了区分当前目录还是 path),比如 ./age
。
文章中提到的命令
-
cat
将文件的内容输出到标准输出。 -
echo
打印内容。 -
cd
切换工作目录。 -
ls
列出当前路径的内容,cmd 下是dir
。
下载 age
前面说到 age 是个轻量的命令行工具,可以免安装直接使用。下载的方式有两种:直接下载可执行文件,或者是下载源码后手动编译。
下载源码后手动编译
该方式需要使用 Git 和 golang。如果你的机器上还没有,可以下载安装。
golang 中国镜像地址: https://golang.google.cn/dl/
安装步骤略,一路点击下一步就行了。虽然安装过程会有英文,但如果这一步都需要截图写到教程里,那你可能不太适合本教程。
$ git clone https://filippo.io/age && cd age
$ go build -o . filippo.io/age/cmd/...
使用 golang 编译会同时下载 age 的依赖,如果网络比较魔法[2],则推荐直接下载 release 的可执行文件。虽然网络魔法的话 release 也下不动。
编译 age 需要 Go 1.13 以上的版本,直接在官网下载则不用考虑这个提示。 |
Homebrew
macOS 上有 brew 包管理器的话,可以直接从 brew 安装,安装的时候会下载 age 的依赖 go。
$ brew tap filippo.io/age https://filippo.io/age
$ brew install age
ArchLinux
$ sudo pacman -Syu git go-pie
$ git clone https://aur.archlinux.org/age.git
$ cd age
$ makepkg -si
go-pie 和 go 是冲突的。如果你的机器上已经安装了 go,直接克隆源码进行编译即可。 |
使用 age
以下命令假定你已将 age 的路径添加到了 path 或使用的是 cmd 且在 age 的目录下。如果你使用的是 bash 且没有添加 path,参照 Git bash 和 cmd 的差异。
生成密钥对
下载好的 age 压缩包解开后会有 age
和 age-keygen
两个文件,首先要执行 age-keygen
来获得密钥对。同时为了方便下次使用,我们将私钥存在文本文件里。
下面的执行结果是我同步操作时的结果,以作为例子。
$ age-keygen -o key.txt
Public key: age1447gr3j9cex96y45manz3sp6jx3sw3vwftltwx7hty6dcqjtjprq8satdy
$ cat key.txt
# created: 2020-03-03T12:49:31+08:00
# public key: age1447gr3j9cex96y45manz3sp6jx3sw3vwftltwx7hty6dcqjtjprq8satdy
AGE-SECRET-KEY-1XT0A0AFQ9CV63X552JS6FX4M36ZSJW36S80J6U7QVVS58H8YAMVQRZTU8Z
这时候就能看到,公钥为 age1447gr3j9cex96y45manz3sp6jx3sw3vwftltwx7hty6dcqjtjprq8satdy
,私钥保存在了名为 key.txt
的文本文件里 (你可以起一个你喜欢的名字,如:epi.txt
等),这时候你可以将公钥发送给即将通讯的人。
当某天密钥丢失的时候,你可以再执行一次 age-keygen
来生成新的密钥对。此处我们再生成一对,当作第二个人的密钥。
$ age-keygen -o key2.txt
Public key: age1h4cq2wxdys6xnqgnrp85qzr9lj3z3ze45f32gcuy500z06rv49tslz7fr5
加密文件
此处我们假定 Alice 和 Bob 要进行加密通信,key.txt
为 Alice 的密钥,key2.txt
为 Bob 的密钥,Alice 要给 Bob 发送一句 "Hello"。
依据上文可以得到 Bob 的公钥为 age1h4cq2wxdys6xnqgnrp85qzr9lj3z3ze45f32gcuy500z06rv49tslz7fr5
,所以 Alice 给 Bob 发送 "Hello" 的命令为:
$ echo "Hello" | age -r age1h4cq2wxdys6xnqgnrp85qzr9lj3z3ze45f32gcuy500z06rv49tslz7fr5 -o hello.txt.age
这里的 -r
为接收者的公钥,-o
是将加密的内容指定加密后输出的文件。
age 的输入方式有文件和 stdin,使用 echo
就是从管道把文本传给 age。假定 Alice 的消息是已经存在了 hello.txt
里,那么我们就不需要 echo 了,直接指定输入文件即可。
$ age -r age1h4cq2wxdys6xnqgnrp85qzr9lj3z3ze45f32gcuy500z06rv49tslz7fr5 -o hello.txt.age hello.txt
解密文件
解密文件比较简单,因为对方用了你的公钥来加密,解密的话只需要用到本地存储的私钥就可以了。
Bob 收到了 Alice 发来的加密文件 hello.txt.age
,将要解密。根据上文 Bob 的私钥存储为 key2.txt,解密的选项为 -d
,指定密钥的选项为 -i
,没有指定选项就是要解密的文件了。
$ age -d -i key2.txt hello.txt.age
Hello
当然,如果加密的是其他非文本文件,则直接输出到 stdout 就不太合适了,你可以通过 -o
来指定输出的文件名。解密之后你可以双击打开它,cat
只是用来做示例。
$ age -d -i key2.txt -o hello.txt hello.txt.age
$ cat hello.txt
Hello
多个接收者
如果有多个接收者,使用 -r
来指定多个密钥即可。
$ age -o example.jpg.age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
-r age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg example.jpg
此处的 \ 是为了避免过长而使用,使用后可以换行的同时而不执行,增加可读性。可以不照抄。 |
其他方式加密
密码 (不推荐)
age 支持通过密码来进行加密,适合面对面说好密码的情况,否则非常不安全[3]。
密码支持手动输入,直接按下回车 age 会使用随机单词组合生成一个。
$ age -p hello.txt > hello.txt.age
Enter passphrase (leave empty to autogenerate a secure one):
Using the autogenerated passphrase "squirrel-situate-rug-equip-dwarf-check-evolve-ghost-style-galaxy".
目前使用 Homebrew 安装的 age 在输入 passphrase 时留空不会自动生成随机密码,已经给作者提 issue |
ssh 密钥
你可以用本地已存在的 ssh 密钥进行加密,但不支持 ssh-agent。
$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZDRcvS8PnhXr30WKSKmf7WKKi92ACUa5nW589WukJz [email protected]
$ age -r "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZDRcvS8PnhXr30WKSKmf7WKKi92ACUa5nW589WukJz" example.jpg > example.jpg.age
$ age -d -i ~/.ssh/id_ed25519 example.jpg.age > example.jpg
可能遇到的问题
不是内部或外部命令 / command not found
你需要将 age 所在的目录添加到 path 里,具体请参照添加 path。
解密后文件乱码
这个问题通常会出现在 Windows 和类 Unix 系统间,文本文件所使用的文字编码不同,非文本文件不受影响 (如 .zip
.docx
)。如果你在 Windows,使用记事本保存的时候将编码设置为 UTF-8。如果你使用的是 Sublime,可以安装 ConvertToUTF8 解决。
文件不能在 32 位机子上运行
这个就得依赖手动编译了,因为 64 位的机器默认会编译成 64 位,releases 也是 64 位的。但是编译 32 位的 age 很简单,你只需要在 32 位的机器上下载源代码编译即可。或者你已经有一台 64 的机器,可以编译了把源文件拷贝过去。
$ set GOARCH=386
$ git clone https://filippo.io/age && cd age
$ go build -o . filippo.io/age/cmd/...
后记
写本文用了一定的时间,但是无法保证覆盖到所有可能遇到的问题。如果你详细阅读本教程后无法学会,可以在 B 站看一下视频演示,也可以在下方评论,收到评论后我会回复并考虑更新本文。
CC BY 4.0
本文链接:https://epliar.com/articles/use-age-to-encrypt/