Restic设计原理( 三 )


这些消息身份验证密钥(k 和 r)用于计算MAC,使用 JSON 中 data字段包含的字节(在删除 Base64 编码并且不包括最后 32 个字节之后) 。如果密码不正确或密钥文件被篡改,则计算出的 MAC 将与数据的最后 16 个字节不匹配,restic 会报错退出 。否则,将使用从 scrypt 派生的加密密钥解密数据 。这将生成一个 JSON ,其中包含此存储库的主加密和消息鉴权密钥(以 Base64 编码) 。restic cat masterkey 命令可用于解密和格式化打印主密钥:
$ restic -r /tmp/restic-repo cat masterkey{"mac": {"k": "evFWd9wWlndL9jc501268g==","r": "E9eEDNSJZgqwTOkDtOp+Dw=="},"encrypt": "UQCqa0lKZ94PygPxMRqkePTZnHRYh1k1pX2k2lM2v3Q=",}存储库中的所有数据都使用这些主密钥进行加密和验证 。对于加密,使用计数器模式下的 AES-256 算法 。对于消息认证,如上所述使用 Poly1305-AES 。
存储库可以有多个不同的密码,每个密码都有一个密钥文件 。这样,无需重新加密所有数据即可更改密码 。
快照(Snapshots)快照表示在特定时间点包含所有文件和子目录的目录 。对于所做的每个备份,都会创建一个新快照 。快照使用JSON文件描述,存储在存储库中“snapshots”目录下的加密文件 。文件名是存储 ID 。此字符串是唯一的,并在 restic 中用于唯一标识快照 。
restic cat snapshot 命令可用于解密和格式化打印快照文件的内容:
$ restic -r /tmp/restic-repo cat snapshot 22a5af1benter passwordfor repository:{"time": "2015-01-02T18:10:50.895208559+01:00","tree": "2da81727b6585232894cfbb8f8bdab8d1eccd3d8f7c92bc934d62e62e618ffdf","dir": "/tmp/testdata","hostname": "kasimir","username": "fd0","uid": 1000,"gid": 100}在这里可以看出,这个快照代表了目录/tmp/testdata的内容 。最重要的字段是tree 。
restic 存储库中的所有内容都根据其 SHA-256 哈希值进行引用 。在保存之前,每个文件都被分割成可变大小的数据块 。所有 Blob 的 SHA-256 哈希值都保存在有序列表中,代表文件的内容 。
为了将这些明文哈希与 Pack 文件中的实际位置相关联,使用了索引 。如果索引不可用,则可以读取所有数据 Blob 的header 。
树(Tree)和数据(Data)快照通过JSON中SHA-256哈希引用树,代表其内容树和数据保存在目录“data”的子目录中的Pack文件中 。
命令 restic cat tree 可用于检查上面引用的树:
$ restic -r /tmp/restic-repo cat tree b8138ab08a4722596ac89c917827358da4672eac68e3c03a8115b88dbf4bfb59enter passwordfor repository:{"nodes": [{"name": "testdata","type": "dir","mode": 493,"mtime": "2014-12-22T14:47:59.912418701+01:00","atime": "2014-12-06T17:49:21.748468803+01:00","ctime": "2014-12-22T14:47:59.912418701+01:00","uid": 1000,"gid": 100,"user": "fd0","inode": 409704562,"content": null,"subtree": "b26e315b0988ddcd1cee64c351d13a100fedbc9fdbb144a67d1b765ab280b4dc"}]}树包包含一组节点(在“node”字段中),其中包含名称和时间戳等元数据 。当节点指向目录时,字段“subtree”包含另一个树对象的ID 。
当使用命令“restic cat tree”时,需要存储哈希来显示树 。上面引用的树可以展开输出为:
$ restic -r /tmp/restic-repo cat tree 8b238c8811cc362693e91a857460c78d3acf7d9edb2f111048691976803cf16eenter passwordfor repository:{"nodes": [{"name": "testfile","type": "file","mode": 420,"mtime": "2014-12-06T17:50:23.34513538+01:00","atime": "2014-12-06T17:50:23.338468713+01:00","ctime": "2014-12-06T17:50:23.34513538+01:00","uid": 1000,"gid": 100,"user": "fd0","inode": 416863351,"size": 1234,"links": 1,"content": ["50f77b3b4291e8411a027b9f9b9e64658181cc676ce6ba9958b95f268cb1109d"]},[...]]}该树包含一个文件 。这一次,subtree 字段不存在,content 字段包含一个 SHA-256 哈希的列表 。
命令 restic cat data 可用于提取和解密指定明文 ID 的数据,例如 对于上述数据:
$ restic -r /tmp/restic-repo cat blob 50f77b3b4291e8411a027b9f9b9e64658181cc676ce6ba9958b95f268cb1109d | sha256sumenter passwordfor repository:50f77b3b4291e8411a027b9f9b9e64658181cc676ce6ba9958b95f268cb1109d-从 sha256sum 的输出可以看出,哈希与上面树中包含的映射的明文哈希匹配,因此返回了正确的数据 。


推荐阅读