DID 去中心化数字身份
身份
国际电子技术委员会将“身份”定义为“一组与实体关联的属性”。这里的实体不仅仅是人,对于机器或者物体都可以是实体,甚至网络中虚拟的东西也可以是实体并拥有身份。
数字身份
随着互联网的出现和普及,传统的身份有了另外一种表现形式,即数字身份。一般认为,数字身份的演进经历了四个阶段,分别是:中心化身份、联盟身份、以用户为中心的身份以及自 我主权身份。
- 中心化身份是由单一的权威机构进行管理和控制的,现在互联网上的大多数身份还是中心化身份。
- 联盟身份的出现解决了中心化身份中身份数据零碎混乱的弊端,此种身份是有多个机构或者联盟进行管理和控制的,用户的身份数据具备了一定程度的可移植性,例如允许用户登录某个网站时, 可以使用其他网站的账户信息,类似于 QQ、微信或者微博的跨平台登录。
- 以用户为中心的身份则将重点集中在去中心化上,通过授权和许可进行身份数据的共享,例如OpenID。
- 自我主权身份才是真正意义上的去中心化的、完全由个人所拥有和控制的身份。
PKI体系
Public Key Infrastructure 的缩写,翻译过来就是公钥基础设施,其主要功能是绑定证书持有者的身份和相关的密钥对(通过为公钥及相关的用户身份信息签发数字证书),为用户提供方便的证书申请、证书作废、证书获取、证书状态查询的途径,并利用数字证书及相关的各种服务(证书发布,黑名单发布,时间戳服务等)实现通信中各实体的身份认证、完整性、抗抵赖性和保密性。PKI体系的中心是CA服务器,CA服务器必须是安全的,可信任的。主要载体是X509格式的证书文件。关于PKI体系可以参考https://blog.csdn.net/lk2684753/article/details/100160856
DID
Decentralized IDentity去中心化身份,简称DID,相对于传统的基于PKI的身份体系,基于区块链建立的DID数字身份系统具有保证数据真实可信、保护用户隐私安全、可移植性强等特征,其优势在于:
- 去中心化:基于区块链,避免了身份数据被单一的中心化权威机构所控制。
- 身份自主可控:基于DPKI (分布式公钥基础设施),每个用户的身份不是由可信第三方控制,而是由其所有者控制,个人能自主管理自己的身份。
- 可信的数据交换:身份相关数据锚定在区块链上,认证的过程不需要依赖于提供身份的应用方。
DID标识
DID标识是一个特定格式的字符串,用来代表一个实体的数字身份,这里的实体可以是人、机、物。DID标识的格式为:
前缀did:是固定的,表示这个字符串是一个did标识字符串。
中间的example被称为DID方法,就是用来表示这个DID标识是用哪一套方案(方法)来进行定义和操作的。这个DID方法我们可以自定义,并且注册到W3C的网站(https://w3c.github.io/did-spec-registries/#did-methods)中。
最后面的部分是在该DID方法下的唯一标识字符串。比如我们做了一个DID系统,我们把方法就起名叫cid吧,想把中国公民的身份证信息都DID化,那么我的DID标识就是:
did:cid:411424**************0
这里我们就使用身份证号码作为cid这个DID方法下的唯一标识。
DID文档
每一个DID标识都会对应一个DID文档(DID Document)。这个文档就是一个JSON字符串,里面一般会包含如下信息:
-
DID文档内容
描述 -
DID主题
-
DID标识符本身,也就是DID文档所描述的该DID。由于DID的全局唯一特性,因此在DID文档中只能有一个DID。
-
公钥
公钥用于数字签名及其他加密操作,这些操作是实现身份验证以及与服务端点建立安全通信等目的的基础。如果 DID 文档中不存在公钥,则必须假定密钥已被撤销或无效,同时必须包含或引用密钥的撤销信息(例如,撤销列表)。 -
身份验证
身份验证的过程是 DID 主题通过加密方式来证明它们与 DID 相关联的过程。 -
授权
授权意味着他人代表 DID 主题执行操作,例如当密钥丢失的时候,可以授权他人更新 DID 文档来协助恢复密钥。 -
服务端点
除了发布身份验证和授权机制之外,DID 文档的另一个主要目的是为主题发现服务端点。服务端点可以表示主题希望公告的任何类型的服务,包括用于进一步发现、身份验证、授权或交互的去中心化身份管理服务。 -
时间戳
文档创建时间和更新时间以上信息并不是必须有,不过一般我们建议包含。我们来看一个具体的DID文档示例:
{
"@context": "https://w3id.org/did/v1",
"id": "did:example:123456789abcdefghi",
"authentication": [{
// 本DID文档对应的DID标识
"id": "did:example:123456789abcdefghi#keys-1",
"type": "RsaVerificationKey2018",
"controller": "did:example:123456789abcdefghi",
//本DID对应的公钥信息
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
}],
"service": [{
// 获取本DID对应的VC的服务接口
"id":"did:example:123456789abcdefghi#vcs",
"type": "VerifiableCredentialService",
"serviceEndpoint": "https://example.com/vc/"
}]
}
DID文档中最重要的就是公钥信息,这是我们接下来要进行VC
和VP
验证的基础。
我们一般是把DID标识作为Key,把DID文档作为Value存储到区块链中,利用区块链不可篡改、共享数据访问的特点,实现接下来在验证身份时能快速访问获取可信数据。
可验证凭证/可验证声明(VC)
(Verifiable Claims 或 Verifiable Credentials,本文接下去都简称VC)是一个 DID 给另一个 DID 的某些属性做背书而发出的描述性声明,并附加自己的数字签名,用以证明这些属性的真实性,可以认为是一种数字证书。
传统的PKI数字证书体系需要CA来颁发,而在DID中也是分为颁发者、持有者、验证者、DID注册系统(也就是区块链),具体关系如图:
- 颁发者Issuer就是证书的颁发机构,比如身份证就是公安机关作为颁发者,毕业证书就是大学作为颁发者。
- 持有者Holder就是证书的持有人,就是我们这些普通人。
- 验证者Verifier就是在我们使用证书时查看我们证书的人或者机构。比如我们入住酒店,前台要验证我们的身份证,那么酒店前台就是验证者;再比如我们入职新公司时需要提供大学毕业证书,新公司HR就是验证者。
- DID注册系统Verifiable Data Registry就是我们存储了DID标识和DID文档的地方,通过DID标识可以查询到对应的DID文档。
当公安机关给我颁发了身份证,在DID中,这个身份证就是VC
。一个VC
也是一个JSON字符串,里面包含如下信息:
- VC元数据,主要就是发行人、发行日期、声明的类型等信息。
- 声明,一个或者多个关于主体的说明。比如身份证作为公安机关颁发给我的
VC
,在声明中会包含:姓名、性别、出生日期、民族、住址等信息。 - 证明,通常就是颁发者的数字签名,保证了本
VC
能够被验证,防止VC
内容被篡改以及验证VC
的颁发者。
下面是官方给出的一个VC
的具体样例:
{
// VC内容所遵循的JSON-LD标准
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
// 本VC的唯一标识,也就是证书ID
"id": "http://example.edu/credentials/1872",
// VC内容的格式
"type": ["VerifiableCredential", "AlumniCredential"],
// 本VC的发行人
"issuer": "https://example.edu/issuers/565049",
// 本VC的发行时间
"issuanceDate": "2010-01-01T19:73:24Z",
// VC声明的具体内容
"credentialSubject": {
// 被声明的人的DID
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
// 声明的断言内容
"alumniOf": {
"id": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"name": [{
"value": "Example University",
"lang": "en"
}, {
"value": "Exemple d'Université",
"lang": "fr"
}]
}
},
// 对本VC的证明
"proof": {
// 签名算法
"type": "RsaSignature2018",
// 签名创建时间
"created": "2017-06-18T21:19:10Z",
// 本证明的目的
"proofPurpose": "assertionMethod",
// 验证本签名的公钥的ID
"verificationMethod": "https://example.edu/issuers/keys/1",
// 数字签名的内容
"jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5X
sITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUc
X16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtj
PAYuNzVBAh4vGHSrQyHUdBBPM"
}
}
因为VC
中具有用户的隐私信息,所以VC
一般保存在私有的存储中,比如用户自己的手机中,或者需要授权的网络地址中。除了前面示例中给出的数据外,我们的VC
还可以有失效日期,比如我们的身份证一般10年有效,过期后就需要重新向颁发者申请新的VC
。
可验证表达(VP)
Verifiable presentation简称VP
,可验证表达是VC
持有者向验证者表名自己身份的数据。一般情况下,我们直接出示VC
全文即可,但是在某些情况下,出于隐私保护的需要,我们并不需要出示完整的VC
内容,只希望选择性披露某些属性,或者不披露任何属性,只需要证明某个断言即可。
比如一个求职者要进入某写字楼面试,写字楼的保安要求登记身份证号码和姓名,但是我们的VC中还包含了民族、住址等信息,我们的求职者不希望将自己的住址暴露给保安,所以他提供给保安的VP中应该只选择性的披露的身份证号码和姓名,其他信息都不披露。
再比如我们规定必须年满18岁才有资格购买香烟,所以一个消费者在购买香烟时必须证明自己已经年满18岁,但是直接出示身份证给收银员又会暴露太多隐私信息,就算选择性披露生日属性,也会让收银员知道了消费者具体的年龄和生日日期,这种情况下消费者只希望在VP中证明自己大于18岁,其他什么信息都不能暴露。
VP
的格式为:
- VP元数据,主要包含了版本,本JSON对象的类型等信息
- VC列表,要对外展示的
VC
的内容,如果是选择性披露或者隐私保护的情形,可能就不包含任何VC。 - 证明,主要就是持有者对本VP的签名信息
下面是官方给出的一个具体的VP的样例:
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": "VerifiablePresentation",
// 本VP包含的VC的内容
"verifiableCredential": [{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/1872",
"type": ["VerifiableCredential", "AlumniCredential"],
"issuer": "https://example.edu/issuers/565049",
"issuanceDate": "2010-01-01T19:73:24Z",
"credentialSubject": {
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"alumniOf": {
"id": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"name": [{
"value": "Example University",
"lang": "en"
}, {
"value": "Exemple d'Université",
"lang": "fr"
}]
}
},
"proof": {
"type": "RsaSignature2018",
"created": "2017-06-18T21:19:10Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "https://example.edu/issuers/keys/1",
"jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5X
sITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUc
X16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtj
PAYuNzVBAh4vGHSrQyHUdBBPM"
}
}],
// Holder对本VP的签名信息
"proof": {
"type": "RsaSignature2018",
"created": "2018-09-14T21:19:10Z",
"proofPurpose": "authentication",
"verificationMethod": "did:example:ebfeb1f712ebc6f1c276e12ec21#keys-1",
// challenge和domain是为了防止重放攻击而设计的
"challenge": "1f44d55f-f161-4938-a659-f8026467f126",
"domain": "4jt78h47fh47",
"jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..kTCYt5
XsITJX1CxPCT8yAV-TVIw5WEuts01mq-pQy7UJiN5mgREEMGlv50aqzpqh4Qq_PbChOMqs
LfRoPsnsgxD-WUcX16dUOqV0G_zS245-kronKb78cPktb3rk-BuQy72IFLN25DYuNzVBAh
4vGHSrQyHUGlcTwLtjPAnKb78"
}
}
DiD的使用流程
场景描述
小明是一个刚刚从大学毕业的应届毕业生,在毕业当天学校颁发了毕业证给小明对应的数字身份,小明拿到毕业证后第二天去公司入职,其中一个环节,公司HR要求验证小明的学历信息,验证完成,小明入职成功。
一般学校会颁发毕业证和学位证两个证,这里我们出于简单起见,就把学位证忽略吧
step1:小明生成DID标识和DID文档
小明要想获得学校颁发的毕业证,那么他必须要有自己的DID,所以他先下载一个数字身份的手机APP,然后创建账号。创建账号的过程就是在手机中生成一个随机是私钥和对应的公钥。这里我们假设我们的DID标识的规则是“did:cid:身份证号”,所以小明在APP中输入自己的身份证号码,生成了一个DID标识:
did:cid:511112200001010015
同时也会生成一个DID文档,内容如下:
{
"@context": "https://w3id.org/did/v1",
"id": "did:cid:511112200001010015",
"version": 1,
"created": “2020-12-08T16:02:20Z",
"updated": “2020-12-08T16:02:20Z",
"publicKey": [
{
"id": "did:cid:511112200001010015#keys-1", "type": "Secp256k1", "publicKeyHex": "02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71" },
{ "id": "did:cid:511112200001010015#keys-2", "type": "Secp256k1", "publicKeyHex": "e3080168ee293053ba33b235d7116a3263d29f1450936b71" } ],
"authentication": ["did:cid:511112200001010015#key-1"],
"recovery": ["did:cid:511112200001010015#key-2"],
"service": [
{
"id": "did:cid:511112200001010015#resolver", "type": "DIDResolve", "serviceEndpoint": "https://did.studyzydemo.com" } ],
"proof": {
"type": "Secp256k1", "creator": "did:cid:511112200001010015#keys-1", "signatureValue": "QNB13Y7Q9...1tzjn4w==" } }
这里我们为该DID设置了两个公钥,一个是小明自己的,用于认证签名等,Key2是系统托管的,用于手机丢失或者系统崩溃导致用户私钥丢失的情况下,帮忙小明找回自己的DID,绑定成一个新的公钥。
Proof部分是小明自己用自己APP里面的私钥对该DID文档的签名。如果我们想进一步增强安全性,可以将proof部分改为由公安机关进行签名。
DID文档生成完成后,APP会将该DID和文档上链到区块链存证,一旦上链完成,所有人都能够查询到小明的这个DID和文档。这里的区块链我们一般都是一个联盟链,并不是任意数据都可以随意写入的,所以小明必须是使用自己的身份证号经过验证确实是本人后才会上链,防止其他人冒用小明身份证号的情况。
step2:Issuer学校颁发毕业证VC给小明
学校本身也有自己的DID,由于学校是教育系统里面颁发的DID,所以规则和小明作为中国公民的DID规则不一样,比如学校的DID标识是:
did:cedu:uestc
这个DID不是学校自己签名的,而是被教育部签名的(教育部的DID是did:corg:moe),我们在区块链中可以找到该DID对应的DID文档如下:
{
"@context": "https://w3id.org/did/v1",
"id": “did:cedu:uestc",
"version": 1,
"created": “2020-12-08T16:02:20Z",
"updated": “2020-12-08T16:02:20Z",
"publicKey": [
{
"id": “did:cedu:uestc#keys-1", "type": "Secp256k1", "publicKeyHex": "3053ba33b235d7116a3e3080168ee293053ba33b235d7116a33053ba33b235d7116a3" },
{ "id": “did:cedu:uestc#keys-2", "type": "Secp256k1", "publicKeyHex": "e293053ba3053ba33b235d7116a3263d29fe293053ba" } ],
"authentication": [“did:cedu:uestc#key-1"],
"recovery": [“did:cedu:uestc#key-2"],
"service": [
{
"id": “did:cedu:uestc#resolver", "type": "DIDResolve", "serviceEndpoint": "https://did.studyzydemo.com" } ],
"proof": {
"type": "Secp256k1", "creator": "did:corg:moe#keys-1", "signatureValue": "QNB13Y7Q9...1tzjn4w==" } }
所有认证过的高校的DID都是由did:corg:moe这个DID创建的,所以这相当于传统的根CA,我们只需要信任这个DID创建的DID,就可以认为是正规的高校。
继续说回颁发毕业证VC
,学校根据小明的学习情况(入学时间、毕业时间、专业、是否结业等信息)以及小明提交的自己的DID,生成VC
如下:
{
// VC内容所遵循的JSON-LD标准
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
// 本VC的唯一标识,也就是证书ID
"id": "uestc/alumni/12345",
// VC内容的格式
"type": ["VerifiableCredential", "AlumniCredential"],
// 本VC的发行人
"issuer": "did:cedu:uestc",
// 本VC的发行时间
"issuanceDate": "2010-07-01T19:73:24Z",
// VC声明的具体内容
"credentialSubject": {
// 被声明的人的DID
"id": "did:cid:511112200001010015",
// 声明内容:毕业院校、专业、学位等
"name":"小明",
"alumniOf": {
"id": "did:cedu:uestc",
"name": [{
"value": "电子科技大学",
"lang": "cn"
}]
},
"degree":"硕士研究生",
"degreeType":"工科",
"college":"计算机学院"
},
// 对本VC的证明
"proof": {
"creator": "did:cedu:uestc#keys-1",
"type": "Secp256k1",
"signatureValue": "3044022051757c2de7032a0c887c3fcef02ca3812fede7ca748254771b9513d8e2bb"
}
}
这里最主要的就是credentialSubject证书的内容和proof颁发学校给出的证明。这个VC生成后会传给小明,小明可以选择将这个内容存储到自己的手机APP中,也可以选择存储到云上,以后需要使用时再读取。
step3:Holder小明提交学历证明VP给Verifier公司HR
接下来小明来到新公司入职,入职当天需要提交学历证明给公司HR,于是小明基于上一步骤生成的VC
再封装一下,生成VP
,VP
的内容如下:
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": "VerifiablePresentation",
// 本VP包含的VC的内容
"verifiableCredential": [{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "uestc/alumni/12345",
"type": ["VerifiableCredential", "AlumniCredential"],
"issuer": "did:cedu:uestc",
"issuanceDate": "2010-07-01T19:73:24Z",
"credentialSubject": {
"id": "did:cid:511112200001010015",
"name":"小明",
"alumniOf": {
"id": "did:cedu:uestc",
"name": [{
"value": "电子科技大学",
"lang": "cn"
}]
},
"degree":"硕士研究生",
"degreeType":"工科",
"college":"计算机学院"
},
"proof": {
"creator": "did:cedu:uestc#keys-1",
"type": "Secp256k1",
"signatureValue": "3044022051757c2de7032a0c887c3fcef02ca3812fede7ca748254771b9513d8e2bb"
}
}],
// Holder小明对本VP的签名信息
"proof": {
"type": "Secp256k1",
"created": "2010-07-02T21:19:10Z",
"proofPurpose": "authentication",
"verificationMethod": "did:cid:511112200001010015#keys-1",
// challenge和domain是为了防止重放攻击而设计的
"challenge": "1f44d55f-f161-4938-a659-f8026467f126",
"domain": "4jt78h47fh47",
"jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..kTCYt5
XsITJX1CxPCT8yAV-TVIw5WEuts01mq-pQy7UJiN5mgREEMGlv50aqzpqh4Qq_PbChOMqs
LfRoPsnsgxD-WUcX16dUOqV0G_zS245-kronKb78cPktb3rk-BuQy72IFLN25DYuNzVBAh
4vGHSrQyHUGlcTwLtjPAnKb78"
}
}
这里比较简单,只是简单的提交整个毕业证全部内容,所以VP
中只需要把VC
签入进去,最后proof的地方小明用自己APP里面的私钥进行签名,表名这个VP
是小明自己生成的即可。这个VP
生成后小明需要将整个VP
的内容提交给新入职公司HR。
step4:Verifier公司HR验证通过小明的VP
公司HR作为验证者在收到小明提交的VP
后首先验证Proof字段,保证VP是小明提交的,而且没有被篡改。接下来提取出其中的VC
内容,对VC
进行验证,验证过程如下:
- 从proof的creator中获得颁发者的DID:did:cedu:uestc
- 通过区块链查询到该DID的文档,在文档中有其创建人和公钥列表,其中我们取keys-1对应的公钥。
- 创建人是did:corg:moe,是可信的DID,所以它创建的DID都是可信的。
- 我们进一步的再用did:corg:moe去区块链读取DID文档,并获得其中的公钥,使用该公钥对did:cedu:uestc对应的文档进行签名验证,确保其没有被篡改。
- 验证通过,我们再用did:cedu:uestc的公钥对小明提交的VC进行签名验证,验证通过,则说明这个证书确实是可信的UESTC颁发的。
- HR检查VC中提供的内容,与小明提交的履历上是否一致,检查完成,进行下一步的入职手续。
以上验证过程中我们至少需要进行三次签名验证。验证VP是小明提交的,验证VC
是UESTC颁发的,验证UESTC的DID是MOE创建的,而MOE是在验证方系统可信列表中的,所以整个就保证了小明提交的证书的可信。
用户属性的选择性披露
我们以最简单的生成DID,颁发VC,验证VP流程介绍了DID的用法,但是在实际生活中,我们并不总是希望直接将整个证件VC亮给验证者看,比如我们去住酒店时,需要登记姓名、身份证号信息,但是如果我们直接把身份证给前台人员的话,前台人员就可以看到我们的民族、住址等信息,对于我们普通人来说,也许觉得没什么,那要是明星、公众人物去住酒店,那么可能前台人员就可能出于各方面的原因偷偷把住址信息记下了或者泄露到网上,给证照本人的生活带来各种麻烦。那么我们有什么办法呢?用户属性的选择性披露能够降低风险。
我们以小明从公安机关获得身份证VC,然后在住酒店时,只出示姓名、照片和身份证号,不对外暴露民族和住址(因为身份证编号里面已经有生日了,所以我们就忽略掉出生日期属性)为例,说明用户属性的选择性披露的处理过程。
准备知识1:默克尔树
默克尔树的目的是为了能够将一个区块中的所有交易形成一个短小的指纹(默克尔根,哈希值),并将这个指纹放到区块头,任何对交易的篡改都会导致指纹变化。而我们使用默克尔树而不是直接将区块中所有的交易直接算哈希的原因是因为我们希望能够进行快速的简单支付验证(SPV)。
我们以4个交易组成的默克尔树为例,我们要验证Data2是否被包含在区块中,只需要给出:
- 要验证的原始数据:Data2
- 要验证的数据所在的位置索引:1 (索引以0开始,所以Data2的索引是1)
- 验证路径:[Hash1,Hash34]
- 默克尔根:MerkleRoot
通过这4个参数,我们就能确认Data2是否被包含在这棵树中了。
准备知识2:基于种子的无限序列
基于前面提到的默克尔树和默克尔验证,我们可以将用户的属性作为Data部分计算默克尔树,比如我们要对身份证上的属性构建默克尔树:
基于上面的默克尔树,我们可以只暴露生日,而不暴露其他字段,然后给出验证路径,从而证明生日数据的真实性。但是这里有个潜在的隐私泄露问题,就是我们会暴露Hash1,而攻击者是可以穷举所有民族数据,算出每个民族的Hash然后进行比对,从而得出我并不想暴露的”民族“属性。那么怎么办呢?最简单的办法就是我们为每个字段都加点”盐“。
用户在生成默克尔树之前,需要先生成一个随机的种子,并将这个种子数据保存下来,然后基于这个种子生成N个序列(N取决与我们默克尔树的叶子节点数),因为我们的种子是随机生成的,所以我们可以认为这个序列也是随机的。最简单的办法就是用哈希函数,不断的对上一个数据进行Hash,从而得到下一个数据。以下是我的序列生成函数
func GenerateSequence256(seed []byte, count int) [][]byte {
result := [][]byte{}
current := seed
for i := 0; i < count; i++ {
current = getHash(current)
result = append(result, current)
}
return result
}
func getHash(input []byte) []byte {
h := sha256.New()
h.Write(input)
return h.Sum(nil)
}
有了这个无限长的随机序列,那么我们就可以将每一个默克尔树叶子节点加盐了,如下图所示:
现在我们Hash值都是加了盐后计算的结果,所以不可能再被碰撞出原始数据。
step1:生成VC
基于上面的两个知识点,我们在准备VC
数据时,除了给出证件中的每个属性外,还需要给出:随机种子seed,默克尔根,发证机关对默克尔根的签名。我们以身份证为例,那么公安机关颁发给我们的身份证VC
如下所示:
{
// VC内容所遵循的JSON-LD标准
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://studyzyexamples.com/identity/v1"
],
// 本VC的唯一标识,也就是证书ID
"id": "vc511112200001010015",
// VC内容的格式
"type": ["VerifiableCredential", "Identity"],
// 本VC的发行人
"issuer": "did:公安部门ID",
// 本VC的发行时间
"issuanceDate": "2010-07-01T19:73:24Z",
// VC声明的具体内容
"credentialSubject": {
// 被声明的人的DID
"id": "did:cid:511112200001010015",
// 声明内容:姓名、性别、生日、民族、住址等
"name":"小明",
"gender":"男",
"birthdate":"2000-01-01",
"nation":"汉",
"address":"A省B市C区D街道xxx号",
//接下来是种子数、默克尔根、公安的签名
"seed":"23523865082340324",
"merkleRoot":"ea59a369466be42d1a4783f09ae0721a5a157d6dba9c4b053d407b5a4b9af145",
"rootSignature":"3066022051757c2de7032a0c887c3fcef02ca3812fede7ca748254771b9513d8e266",
"signer":"did:公安部门ID#keys-1"
},
// 对本VC的证明
"proof": {
"creator": "did:公安部门ID#keys-1",
"type": "Secp256k1",
"signatureValue": "3044022051757c2de7032a0c887c3fcef02ca3812fede7ca748254771b9513d8e2bb"
}
}
我们需要注意的是对默克尔根的签名并不是在proof字段里面,而是在credentialSubject里面,proof里面的签名是对整个VC数据的签名,而rootSignature是公安机关对构造的默克尔树的根哈希进行的签名。
step2:生成VP
接下来假如小明要去参加一个生日当天免费送礼品的活动,活动方要验证小明的出生日期,于是小明可根据上一步骤的VC
,生成对应的VP
,其中只暴露生日字段,其他身份属性不暴露,示例如下:
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://studyzyexamples.com/identity/v1"
],
"type": "VerifiablePresentation",
// 本VP包含的VC的内容
"verifiableCredential": [{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://studyzyexamples.com/identity/v1"
],
"id": "vc511112200001010015",
"type": ["VerifiableCredential", "Identity"],
"issuer": "did:公安部门ID",
"issuanceDate": "2010-07-01T19:73:24Z",
"credentialSubject": {
"id": "did:cid:511112200001010015",
//以下是要选择性披露的内容
"birthdate":"2000-01-01",
//以下是验证披露字段有效性的数据
//数据在默克尔树中的索引
"dataIndex":2,
//本数据加盐的值
"salt":"6b264354ed367ced527a86d38f75f9c3888bd3939f548cc48d93af435890b84a",
//默克尔验证路径
"merklesibling":"34b64151443c3124620bf4ff69a05e97d580f0878b374b8343c6a5c3d8223435 9d2b5b35ccb5bf18747c1f5dc05771c68ce613e6eb0c5f5ef77cec8ba3e9da67 bb82c63d4e21525125bf66a6724fbb4dcbded26aae2baa2633235dc12730016e",
//默克尔根哈希
"merkleRoot":"ea59a369466be42d1a4783f09ae0721a5a157d6dba9c4b053d407b5a4b9af145",
//公安机关对默克尔根的签名
"rootSignature":"3066022051757c2de7032a0c887c3fcef02ca3812fede7ca748254771b9513d8e266",
//用的公安机关哪个Key进行的签名
"signer":"did:公安部门ID#keys-1"
},
}],
// Holder小明对本VP的签名信息
"proof": {
"type": "Secp256k1",
"created": "2010-07-02T21:19:10Z",
"proofPurpose": "authentication",
"verificationMethod": "did:cid:511112200001010015#keys-1",
// challenge和domain是为了防止重放攻击而设计的
"challenge": "1f44d55f-f161-4938-a659-f8026467f126",
"domain": "4jt78h47fh47",
"jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..kTCYt5
XsITJX1CxPCT8yAV-TVIw5WEuts01mq-pQy7UJiN5mgREEMGlv50aqzpqh4Qq_PbChOMqs
LfRoPsnsgxD-WUcX16dUOqV0G_zS245-kronKb78cPktb3rk-BuQy72IFLN25DYuNzVBAh
4vGHSrQyHUGlcTwLtjPAnKb78"
}
}
这里我们给出了选择披露的字段birthdate
,然后给出了要进行默克尔验证的几个必不可少的字段:
- “birthdate”:"2000-01-01”,要披露的原始数据内容。
- dataIndex,披露字段在构架默克尔树时在叶子节的索引,因为我们这里按:姓名、性别、生日、民族、住址排序,所以生日的索引值是2.
- salt,对birthdate这个字段加的盐,这个数据小明可以根据自己VC中的seed和dataIndex计算得到。
- merkleSibling是进行默克尔验证所需的路径,以前面提到的4个Data为例,如果我们要算Data2的验证路径,那么就是Hash1,Hash34。
- merkleRoot默克尔根,这个就不再累述。
- rootSignature和signer是用来验证默克尔根的合法性的。merkleRoot、rootSignature、signer验证通过,则说明这个默克尔根是公安部认证过的。
step3:验证VP
商家在收到用户提交的VP
后,需要进行逐步的验证,主要包括以下步骤:
1.根据小明的DID从区块链中获取小明的DID文档,从中获得公钥,验证VP签名真实有效。
2.根据VC中的issuer,从区块链中获得公安机关的DID文档,从文档中获得公钥,另外也验证该DID是一个可信的DID。
3.根据公安部门的公钥,验证默克尔根的签名是否正确。
4.对披露字段、Dataindex、Salt、MerkleSibling、MerkleRoot等进行默克尔验证,保证披露字段是公安机关认证过的。
5.以上所有步骤验证通过,显示可信的披露内容:“birthdate”:"2000-01-01”。
商家验证完成了小明的出生日期,但是并没有获得除了出生日期之外的其他身份信息,从而实现了选择性披露。
DID的应用
无密码安全登录
这个使用场景大家应该都很熟悉了,就类似于微信扫码登录,当我们要注册或者登录一个网站时,不需要再填写用户名、密码、邮箱之类的信息,只需要用手机里的数字身份APP扫描登录页的二维码,然后在APP中弹出扫码后的信息,选择确认登录即可。使用DID的APP与传统的微信扫码登录不同之处就在于DID中用户的身份信息是用户自己掌握的,而微信扫码登录的身份信息是腾讯掌握的,如果哪一天腾讯封禁了你的微信账号,那么你将无法登录所有之前使用微信登录的网站。而DID不会有这个问题,因为没有人能够封禁你的DID。使用DID实现无密码登录的流程如下:
- 用户打开要登录的网站,网站服务器生成一个包含随机分配的ID、网站DID、网站服务器URL的二维码。
- 用户解锁手机中的DID APP,并扫描网站上的二维码。
- APP获得二维码中的ID和服务器提交URL,生成登录请求,并使用网站DID去区块链查询DID文档,获得网站服务器的公钥,用公钥加密请求数据,发送到网站服务器。
- 网站服务器用私钥解密登录请求,并在区块链中查询DID对应的DID文档,从中获得公钥,用公钥验证签名,确保DID为对应的用户。
- 网站服务器验证通过,刷新登录页面为已登录状态。
从整个流程中我们可以看到,服务器并不知道用户的密码,而且也无法获得除用户的DID和DID文档以外的任何信息,从而保证了用户隐私数据的安全。从此再也不用担心XX网站用户信息泄露或者密码被黑客撞库,登录了其他网站盗取有用信息的情况发生。
身份认证
在大量的涉及价值的网络中,尤其是金融产品的网络,都要求做好KYC和AML。尤其是KYC,需要获得用户的一些身份信息,而每注册一个金融网站就需要认证一次身份信息十分繁复,使用DID进行身份认证可以简化这个流程。以某互联网金融APP为例,如果一个新用户想在上面做投资,那么需要提供手机验证码、身份证照片验证、人脸识别验证、录制视频等手续。而如果该用户又去另一个互联网金融的APP里面,又得再次进行相关的验证,非常的麻烦。而如果基于DID,可以将身份认证的手续大为简化。当然要进行身份认证的前提是:公安机关、大学等身份信息、证书颁发机构已经将VC生成,并发到了用户手中。用户将VC存储在自己的云空间或者自己的手机中。
在用户通过无密码登录APP后,进行实名认证的过程如下:
- 用户登录到网站或者APP或者商家点击认证按钮。
- 服务器根据业务需求,生成需要认证的信息的请求,并将请求以二维码或者其他方式发送给用户DID的APP。
- DID APP收到认证请求后,查询本DID是否有满足要求的VC,是否有对应的字段等,如果满足要求,显示认证的内容,并请求用户通过指纹或者密码解锁私钥进行签名,以生成VP。
- 用户在确认信息无误后,解锁私钥,生成VP,并将VP以二维码或者直接回传商家服务器的形式,发送到商家服务器。
- 商家服务器收到VP后,验证VP签名无误,满足验证的要求,显示验证通过。商家服务器将VP保存,并关联用户DID。
除了金融场景要求的KYC之外,前面我们也举例过的公司入职时要验证学历、酒店入住的时候要验证身份、买烟酒时要验证年龄大于18岁,在购买景区门票时验证学生身份享受学生折扣等
电子签名
在传统的电子签名方案中,用户需要预制一个U盾,该U盾中含有分配给该用户的私钥还有给该用户颁发的证书,每次签名需要插入U盾,安装插件,才能正常使用。而基于U盾的电子签名方案具有以下几个问题:
1.需要很长的时间来准备U盾(制作证书),所以不能立刻申请,立刻使用。
2.U盾必须随身携带,而用户一般只有随身带手机的习惯,没有随身带U盾的习惯。
3.签名方在首次签名后可以对原文件进行修改,然后重新签名,仍然验证通过的
基于数字身份DID的电子签名方案可以很好的解决前面提到的三个问题。其使用流程如下:
- 用户通过自己的手机创建好DID后,先向可信发证方发起请求,获得VC,并将VC存储在用户端。该VC就相当于传统PKI体系的证书文件。
- 用户在审阅文档确认没问题后,计算文档Hash,将文档Hash和其他摘要信息通过二维码或者其他方式发送到DID APP中。
- DID APP请求用户解锁私钥,并用私钥对文档哈希进行签名,并同时将:DID、文档Hash、签名值上链。
- PC端检索区块链,获得上一步骤上链的DID、签名值等信息,验证通过,将签名结果展示在文档中。
以上步骤中,因为VC
的生成和下载都是软件实现,所以不需要长时间等待U盾制作;而且私钥通过加密保存到手机中,不用单独再随身带个U盾;签名结果直接上链,防止篡改,预防签名方多次签名同一个文档多个版本的情况
个人隐私保护
用户身份属性的选择性披露和零知识证明,用户在亮证的时候只披露验证方需要的信息,而不会把整个证件的所有信息暴露,从而实现了个人隐私保护的目的
外还有进一步的一种叫PDC(个人数据中心)的方案,个人数据都加密保存在个人的数据中心中并与个人的DID关联,每个人对自己的数据负责,当需要获取用户的某些隐私数据时,需要该DID的授权才能解密访问。
物联网标识
前面提到的几个应用场景都是针对人的身份,实际上IOT也可以与DID进行紧密结合,我们给每个IOT设备都分配其独一无二的IDD,基于物联网+区块链+DID构建:商品溯源、车联网、智能制造、智慧城市等应用场景。
以制造业中的制造机器为例,每个机器都有一个DID,该DID是由机器的制造商生成并赋予每台机器的,当机器运转时会产生大量的生产数据,该机器会将数据签名,将非敏感生产数据、签名结果和DID上链。机器的制造商可以根据链上数据得知机器的运行情况,便于更好的售后保养服务。当企业需要贷款时,银行可以根据区块链上的生产数据,并结合机器制造商的背书,判断企业的生产经营情况,评估贷款风险。
我们再以高价值商品的物联网防伪溯源为例,当每个商品被制造出来时,商家就为其IOT设备生产私钥并创建唯一的DID。因为私钥无法复制导出,所以只有在区块链上登记了DID的商品才是正品。而且商品的DID可以映射对应的非同质化通证,以数字化的形式表现商品的流转过程。
随身带个U盾;签名结果直接上链,防止篡改,预防签名方多次签名同一个文档多个版本的情况
个人隐私保护
用户身份属性的选择性披露和零知识证明,用户在亮证的时候只披露验证方需要的信息,而不会把整个证件的所有信息暴露,从而实现了个人隐私保护的目的
外还有进一步的一种叫PDC(个人数据中心)的方案,个人数据都加密保存在个人的数据中心中并与个人的DID关联,每个人对自己的数据负责,当需要获取用户的某些隐私数据时,需要该DID的授权才能解密访问。
物联网标识
前面提到的几个应用场景都是针对人的身份,实际上IOT也可以与DID进行紧密结合,我们给每个IOT设备都分配其独一无二的IDD,基于物联网+区块链+DID构建:商品溯源、车联网、智能制造、智慧城市等应用场景。
以制造业中的制造机器为例,每个机器都有一个DID,该DID是由机器的制造商生成并赋予每台机器的,当机器运转时会产生大量的生产数据,该机器会将数据签名,将非敏感生产数据、签名结果和DID上链。机器的制造商可以根据链上数据得知机器的运行情况,便于更好的售后保养服务。当企业需要贷款时,银行可以根据区块链上的生产数据,并结合机器制造商的背书,判断企业的生产经营情况,评估贷款风险。
我们再以高价值商品的物联网防伪溯源为例,当每个商品被制造出来时,商家就为其IOT设备生产私钥并创建唯一的DID。因为私钥无法复制导出,所以只有在区块链上登记了DID的商品才是正品。而且商品的DID可以映射对应的非同质化通证,以数字化的形式表现商品的流转过程。
转载 https://www.cnblogs.com/studyzy/p/14181526.html