上期我们为大家介绍了 Open Badges 和 Blockcerts Schema 以及两者之间的区别,本期我们将继续连载翻译 Rebooting Web of Trust 组织在 RWOT IX — Prague, 2019会议上的论文《Blockcerts V3 Proposal》,探讨 Blockerts 作为可验证凭证是如何实现的。
原文:
https://github.com/WebOfTrustInfo/rwot9-prague/blob/master/final-documents/BlockcertsV3.md
作者:
Anthony Ronning,Wong Wai Chung
图 | 网络
通过前面的讲述,我们了解了 Blockcerts 在 Open badges 的基础上附加了一些特定内容(即 recipientProfile、 verification 以及 signature 等),我们可以将这些内容和可验证凭证(Verifiable Credential,VC)上的内容进行对应。
本质上,Blockcerts 的 recipientProfile 可以被替换为 credentialSubject.id 和 credentialSubject.name。
"recipientProfile": {
"type": [
"RecipientProfile",
"Extension"
],
"publicKey": "ecdsa-koblitz-pubkey:mtr98kany9G1XYNU74pRnfBQmaCg2FZLmc",
"name": "Eularia Landroth"
}
可以变成:
"credentialSubject": {
"id": "ecdsa-koblitz-pubkey:mtr98kany9G1XYNU74pRnfBQmaCg2FZLmc",
"name": "Eularia Landroth",
"alumniOf": {
"id": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"name": [{
"value": "Example University",
"lang": "en"
}, {
"value": "Exemple d'Université",
"lang": "fr"
}]
}
}
当前,Blockcerts中接收者使用 ecdsa-koblitz-pubkey 作为公钥。由于这是一个有效的 URI,因此它也可以用于可验证凭证。理想情况下,可使用 DID 来代替,以使得其在整个 VC / DID 生态系统中得到更好的支持。
就像前面提到的 Blockcerts 当前模式和示例中指出的一样,Blockcerts 的 verification 用于验证发行者的公钥和用于向区块链签发交易的公钥是否匹配。
这可能是一个冗余属性。因为可验证凭证也具有可验证不变性的 proof 属性,"issuer profile" 已经指定了其用于签发的密钥,并且在解析区块链交易时将知道这密钥是用于签发的。
除非有很强的理由在将此属性移到 VC 模式时将其保留在 Blockcerts 中,否则我们建议在 Blockcerts V3 中删除 verification 属性。
可验证凭据需要有个 proof 属性,该属性用于验证 VC 的不变性,并证明某个发行者已对该 VC 进行了签名。在 VC 之前,Blockcerts 使用 signature 属性来证明不变性。如果我们已经被要求实施 proof 属性,那么 signature 属性将提供什么作用?
时间戳是 proof 方法中没有和签名密钥一起提供的重要属性。一个 created 日期可应用于 proof,但由于可以与任何日期一起创建,这就不能证明它在某一时间的存在性。在这里,使用区块链可能是有好处的,因为它证明了文件在交易发生时以高度确定性的方式存在(从技术上讲,由于哈希函数的特点,碰撞仍然可能存在,从而导致文件的存在性存疑)。
为了符合可验证凭证的要求,我们需要使用其他签名证明。目前,MerkleProof2019 正在规范中,并将与可验证凭证兼容。
MerkleProof2019:
https://w3c-dvcg.github.io/lds-merkle-proof-2019/
虽然在可验证凭证中允许多个签名,但 Blockcerts 规范应仅规定需要区块链证明的存在。同时提供诸如 RSA 签名的数字签名和 MerkleProof2019 签名可能有好处,以便可以为可能尚不支持 MerkleProof2019 的验证者提供更好的互操作性。
下面是一个例子:
...
[Cert Data Hash]
...
"proof": {
"type": "MerkleProof2019",
"creator": "did:example:abcdefghij0123456789",
"created": "2017-09-23T20:21:34Z",
"domain": "example.org",
"nonce": "2bbgh3dgjg2302d-d2b3gi423d42",
"proofValue":
"z76WGJzY2rXtSiZ8BDwU4VgcLqcMEm2dXdgVVS1QCZQUptZ5P8n5YCcnbuMUASYhVNihae7m8VeYvfViYf2KqTMVEH1B"
}
【注意】:在新的 MerkleProof2019 中 ,proofValue 是 JSON 文件中的一个 CBOR 编码。
以上内容解码为:
{
"merkleRoot": "3c9ee831b8705f2fbe09f8b3a92247eed88cdc90418c024924be668fdc92e781",
"targetHash": "c65c6184e3d5a945ddb5437e93ea312411fd33aa1def22b0746d6ecd4aa30f20",
"path": [{
"right": "51b4e22ed024ec7f38dc68b0bf78c87eda525ab0896b75d2064bdb9fc60b2698"
}, {
"right": "61c56cca660b2e616d0bd62775e728f50275ae44adf12d1bfb9b9c507a14766b"
}],
"anchors": [{
"sourceId": "582733d7cef8035d87cecc9ebbe13b3a2f6cc52583fbcd2b9709f20a6b8b56b3",
"type": "BTCOpReturn"
}]
}
除了存在性证明外,在考虑撤销用例时,使用区块链还可以带来其他好处。举一个使用 RSA 密钥对基于非区块链的 VC 进行签名的例子。签名证明具有与签名相关联的 createdDate,但是我们不能证明此日期在事实上是正确的,只能证明签名密钥的人或过程声称它们是签名时间。
图 | 网络
在大多数情况下,使用自己密钥签名的颁发者应该在正确的时间签名。但是,在签名密钥被盗的情况下,盗取密钥的人可能希望颁发一个以前的证书。举个例子,盗取密钥的人可以为自己颁发一个时间提前的大学毕业证书。
大学会意识到他们的密钥被盗或者泄漏了,或者他们只是有良好的密钥轮换习惯。在上述任何一种情况下,真正的颁发者现在都会将其密钥的过期时间设置为已知盗窃发生之前来撤销该密钥。
由于凭证日期不可信任,因此我们无法确定给定密钥的凭证属于 createdDate 和 revocationDate 范围。对于由已泄漏密钥颁发出来的凭证,需要在凭证验证过程中因签名密钥验证问题而显示失败(或至少发出警告)。由已泄漏密钥颁发出来的不良凭证可能会影响从该颁发者采用此密钥为其他接收者颁发的凭证状态。当涉及到终身证书时,这点还无法令人满意。
因此,通过利用区块链的可信时间戳,我们可以计算出真实的发行日期,并确定如果颁发者在特定日期撤销了某个签名密钥,则在该日期之前在区块链上锚定过的每个凭证都不会受到密钥撤销的影响。
图 | 网络
除了上面指出的现有字段外,Blockcerts V2 中还有几个非标准字段在生态系统中使用,因此可以使其标准化,并从中受益。
display
在 Blockcerts V2 中,我们已经非正式地建立了对 displayHtml 的大量支持,这已经在移动钱包、验证程序以及第三方库等中出现。
在提议对 V3 进行更改时,如果能够为显示提供正式支持将会大有益处。扩展过去的 displayHtml,我们应该允许支持任何类型的显示。有些人可能不想使用 html,而是使用 pdf、图像等。
选项1
模式可以仅使用 type 和 data 属性。
下面是一个例子:
"display": {
"type": "html",
"data": "
hello world
"}
选项2
或者,我们可以改用 DATA URL:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
"display": "data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E"
最初,官方的 Blockcerts Universal Verifier 可能仅正式支持 HTML,但是它将允许其他人创建具有不同显示类型的有效 Blockcerts。官方验证程序在不了解数据 URL 时应退回到默认显示,就像今天当缺失 displayHtml 时一样的做法。
metadata
类似于 display / displayHtml 的问题,我们目前对使用 metadatajson 属性没有官方标准。尽管如此,我们在移动应用程序和验证程序中都具有非官方支持,用于向查看器显示一些元数据信息。
选项1
我们可以将其添加到标准中,但是允许使用不同类型的元数据格式,例如 XSD。这将允许颁发者利用不同的格式,并继续在某些 Blockcerts 生态系统中正式支持它们。
实现可能类似于 display,添加 type 和 data:
"metadata": {
"type": "json",
"data": "{\"test\": true}"
}
选项2
我们可以完全删除 metadatajson。相反,元数据可以由 credentialSubject 字段获取。可验证凭证规范对 credentialSubject 中可提及的信息类型没有要求;因为这是“holder”和“ subject”属性所在的位置,所以有意义的是,任何其他类型的元数据都将位于此处。这将与其他非 Blockcerts 可验证凭证以及其他可验证凭证钱包保持一致并可以互操作。
选项3
我们可以保持原样,我们根本没有更改此项的要求。选择选项2将消除对某些可能重复信息的需要,但是按原样保留将允许颁发者将要显示给用户并由系统解析的元数据信息更加明确化。
值得注意的是,保留 metadataJson 或将其更改为 metadata 很有可能会特定于 Blockcerts,而更广泛的可验证凭证生态系统则可能无法理解该属性。
推荐的方法是仅从 credentialSubject 中提取其他元数据信息(选项2的做法)。
本期,我们探讨了 Blockerts 作为可验证凭证来实现的几种模式,相信大家一定有所收获。下期我们将继续为大家连载翻译本篇论文的最后一部分,介绍 Blockerts V3 的一些示例及相关讨论,欢迎大家关注。