6 个稳定版本
1.0.12 | 2023 年 3 月 2 日 |
---|---|
1.0.10 | 2023 年 2 月 28 日 |
1.0.4 | 2023 年 2 月 19 日 |
#1009 在 密码学 中
465KB
435 行
包含 (ELF 可执行文件/库, 1MB) turnstile
旋转门 - 单向加密
旋转门加密数据,使得数据只能在另一台计算机上解密(不能在加密计算机上解密)。
从密码学角度来看,旋转门仅仅是围绕libsodium的box
的一个包装。使用ECIES变体可以实现类似的功能。
加密
- 源计算机生成一个临时密钥对。
- 使用源计算机的私钥和目标计算机的公钥生成预计算密钥。
- 使用预计算密钥加密消息。
- 源计算机的临时公钥是加密消息的一部分,但不会保留。
- 丢弃源计算机的临时私钥。
解密
- 目标计算机有一个长期密钥对。
- 使用目标计算机的私钥和源计算机的公钥(包含在加密消息中)生成预计算密钥。
- 使用预计算密钥解密消息。
用例
日志记录
通过旋转门管道日志,使得日志只有在移动到具有目标私钥的计算机上才能读取。这意味着如果Web服务器等被入侵,历史日志也会受到保护。
加密文件
如果您被提供了收件人的公钥,您可以将数据加密并放在公共位置,知道只有他们才能解密它。(您甚至无法自己解密它,所以如果需要,您最好保留原始数据。)
您已经可以使用openssl或PGP做类似的事情,所以这并不太令人兴奋。
用法
在目标机器上创建base62 ed25519密钥
target:/some/dir $ turnstile keygen
new secret key written into /home/fadedbee/.turnstile/i8q8p2L8gZpZsPD8NRcTiFfQHLfrhoq3IvsaEwWzPJH.secret
在源机器上加密流
source:/other/dir $ echo "hello world" | turnstile encrypt i8q8p2L8gZpZsPD8NRcTiFfQHLfrhoq3IvsaEwWzPJH > filename.txt.t7e
在源机器上加密文件
source:/other/dir $ turnstile -i filename.txt -o filename.txt.t7e encrypt i8q8p2L8gZpZsPD8NRcTiFfQHLfrhoq3IvsaEwWzPJH
在目标机器上解密流
target:/some/dir $ cat filename.txt.t7e | turnstile decrypt
hello world
(filename.txt.t7e
包含目标计算机的公钥。解密会从 /home/fadedbee/.turnstile/i8q8p2L8gZpZsPD8NRcTiFfQHLfrhoq3IvsaEwWzPJH.secret
读取相关的私钥。)
在目标机器上解密文件
target:/some/dir $ turnstile -i filename.txt -o filename.txt.t7e -o decrypted.txt decrypt
target:/some/dir $ cat decrypted.txt
hello world
版本 1.0.X 的流/文件格式。
头部
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|FA|DE|DB|EE|t |u |r |n |s |t |i |l |e |Version |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
+ Encryptor's Public Key +
| |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
+ Intended Decryptor's Public Key |
| (informational only) |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Initial Nonce |
+ +--+--+--+--+--+--+--+--+
| |
+--+--+--+--+--+--+--+--+
数据块
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Len | |
+--+--+ +
| |
+ Ciphertext +
| |
v v
最后一个数据块
+--+--+
|00 00|
+--+--+
设计选择
权衡和妥协的文档。
要求私钥包含在文件中(在 ~/.turnstile 中)
本可以通过命令行指定目标密钥,而不是使用 ~/.turnstile
。
对于多用户机器来说,这可能会不安全,因为ps
和top
会显示其他用户的命令行参数。
使用Base62
- Base64更常见,但需要在shell命令中进行引号处理,并且不易于复制粘贴。
- Base58有哨兵,可能对手动输入密钥有帮助,但长度更长且大小可变。
- 巧合的是,43个62进制的数字提供了256.03位。log2(62)*43 == 256.03
将目标公钥包含在加密输出中
目标公钥在加密输出中存在没有加密学的需要,但我们仍然包含它。
优点
- 允许解密只尝试一个密钥,而不是所有已知的密钥。
- 用户可以检查.t7e文件以找到他们需要用于解密的公钥。
缺点
- 向加密输出中添加可识别的信息。
使用~/.turnstile而不是~/.ssh中的Ed25519 SSH密钥
turnstile使用的加密与SSH的.ssh/id_ed25519.pub文件兼容。
使用现有的密钥会更好,但是
- 我们需要向用户解释SSH密钥类型之间的区别。
- 需要使用Base64和引号。
在块中使用16位的密文长度
为了处理流数据,我们必须将输入拆分成块,每个块可以依次解密。(解密包括完整性检查。)
较小的块有更多的开销,但允许较大的块则意味着每个小块有更多的长度开销。
我们可以使用可变大小的整数来表示长度,这可以节省一些空间,但会以一些CPU周期和复杂性为代价。
目前,我们已确定最大块大小为65,535字节。
对于大文件,每65,519字节的明文会产生一个包含2字节长度和65,535字节密文的块。
这不到0.03%的开销。鉴于使用u16表示块长度简单易行,这对于v1.0.0版本是可以接受的。
随机数生成
随机数不得为任何给定的公钥和私钥对重复使用。
每个块都使用不同的随机数进行加密,这个随机数只是初始随机数与块号的异或。
由于每条消息都是使用不同的密钥加密的,因此没有必要让初始随机数不同。但我们随机生成初始随机数并将其写入标题,以防万一...
依赖项
~21MB
~143K SLoC