一项为您的数据签署证据的服务,总会面临一个显而易见的诱惑:把数据放进证据里。这样一来,搜索会变得更方便,技术支持会变得更容易,我们也能够做出功能更丰富的仪表板。我们很早就决定,Trustvice 的回执不会这样做:回执携带的是它所描述对象的哈希值,而不是内容本身。
本文将解释我们这样做的原因,以及在哪些地方,如果没有您的配合,这一设计就无法再为您提供保护。
需要四处流转的证据#
一份回执,只有在您能够把它交给某个人的时候才真正有用:一位审计师、一个交易对手,或者一位调解人。回执之中的任何内容,都可以被您交给的那个人完整地读到。如果回执中直接包含了内容本身,那么您所分享出去的每一份回执都会泄露一些信息,而您每一次都不得不仔细考虑应当如何进行脱敏处理。
而 SHA-256 哈希值则可以完全避免这一点。它是由 64 个十六进制字符组成的一串值,能够唯一标识您内容的确切字节,却不会泄露这些字节本身。于是,这份回执实际上是在说:在这个时间,这些字节以这个标签被出示过。字节本身则始终由您自己来保管。当它变得重要时,您就把它们拿出来,任何人都可以对其计算哈希,而这个哈希要么与回执完全相符,要么就不相符。
仅仅计算哈希还不够的地方#
如果我们只说到这里就停下,那其实就是在误导您。哈希只有在满足一个前提条件时,才能很好地保护内容,而且回执中还有一些字段根本就不是哈希值。
哈希对内容的隐藏程度,取决于内容有多难被猜到#
SHA-256 虽然无法被逆向还原,但它是可以被猜中的。如果输入的可能性很少,例如一个“是”或“否”的回答、一个电子邮件地址、一个简短的代码或者一个已知的模板,那么任何一个持有这份回执的人,都可以对各种候选值逐一计算哈希,然后进行比较。对于这类内容,请在您计算哈希的内容中加入一个随机值,也就是一个 nonce,并把这个 nonce 与原件保存在一起。这样一来,回执就能够证明内容的存在,同时又不会让读者猜出它究竟是什么。
有些字段是以明文形式写入的#
您所选择的标签和其他自由文本字段都以明文写入,一旦被签入回执,就会一直保留在其中。请使用不透明的标识符,例如订单号或内部 ID,并将对照表保存在您自己这一侧。
对确切的字节计算哈希#
哈希所标识的是字节,而不是字节所表达的含义。末尾多出的一个换行符、用 \r\n 代替了 \n,或者采用了不同的 Unicode 规范化形式,都会得到一个不同的哈希值。对于文本,请一次性地确定好编码和换行方式,并且在之后始终保持一致。对于结构化的记录,请保存您当初计算哈希时所用的确切字节,而不是重新序列化的结果:之后用不同的键顺序再执行一次 JSON.stringify,就会得到一个不同的哈希值。对于多个文件,请对一份列出了每一个文件各自哈希值的清单计算哈希,然后再为这份清单生成证明。
保留您的原件#
请为一个后果提前做好规划:回执无法重现内容本身。 如果您丢失了原件,回执依然能够通过验证,但它就再也无法就您能够出示的文档证明任何有用的事情。请将原件以一次写入的方式,与其回执一同保存。
删除与证据的本质#
有一个局限,是任何一种设计都无法消除的。一份您已经交给了他人的回执,无论我们做什么,对方都依然可以验证它,因为验证只需要这份回执和一把公钥。而正是这一特性,才让它成为了真正的证据。这也正是上面那些建议之所以重要的原因:不要把任何个人数据放进明文字段之中,这样一来,删除一份回执的问题就很少会变得棘手。通常只需在您自己的存储中删除原件就足够了,因为回执中保留的只是它的哈希值。
简而言之#
我们所签名的,是关于您数据的事实,而不是这些数据本身。哈希优先,意味着回执可以四处流转,也意味着验证永远不需要信任我们的存储。它并不能让一个可被猜测的值变得私密,也无法保护您写在明文字段中的内容。对于较小的输入请使用随机数,对于标签请使用不透明的 ID,并保留好您的原件。
更多内容,请阅读回执能证明什么,又不能证明什么以及我们的安全页面。
