查看原文
其他

Internet Identity(II)的设计和实现:第二篇

ICPL 2022-06-09


本期概要

在上一篇文章中,介绍了 Internet Identity(II)的设计(Internet Identity(II)的设计和实现:第一篇),这篇文章来聊聊实现逻辑和核心代码。


本文主要包含三个部分:


  1. Anchor 和 设备管理

  2. 如何生成身份(Principal)

  3. Delegation 实现逻辑


II 实现的函数如下:


II 的函数列表


前面部分是 Anchor 和 设备管理,get_principal 是生成身份,prepare_delegation 和 get_delegation 是 Delegation 的实现。



Anchor 和 设备管理


设备的数据结构:


设备的数据结构


DeviceData 主要包括 pubkey(公钥)、alias(别名)、credential_id(凭据,可选,用于 WebAuthN 认证)、purpose(用途)、key_type(类型)。


设备分为普通设备和用于恢复的设备:


  1. 普通设备,purpose 为 authentication,key_type 为 unknown

  2. 用于恢复的设备,purpose 为 recovery,key_type 又分为两种情况:

  • 如果使用助记词,key_type 为 seed_phrase

  • 如果使用安全秘钥,key_type 为 cross_platform


在第一次使用 II,创建 Anchor 时,会提示输入第一个设备名称,点击 Create 后,会调用后端的 register 函数同时创建 Anchor 以及增加第一个设备。


创建 Anchor 和第一个设备


register 函数


register 几个重要的点:


  1. check_entry_limits 是检查一些限制,包括别名、公钥和凭据的长度限制

  2. store.allocate_user_number() 会生成一个 Anchor,它是自增 ID,加 1 即可

  3. 然后把 Anchor 和设备信息保存下来


注册 Anchor 之后,可以继续增加设备,这时候调用的是 add 函数。


add 函数


add 函数需要注意的一点是,trap_if_not_authenticated 会验证请求的合法性,验证方法是检查前端的身份(caller,通过设备公钥生成)是不是在已知的设备身份列表里。


trap_if_not_authenticated 不仅在设备的函数中做验证,也会为身份和 Delegation 的函数做验证。


具体代码是:


trap_if_not_authenticated


当然,设备支持还支持删除,这里不再赘述。



 如何生成身份(Principal)


在上篇文章中有说过,身份主要是根据 Anchor(user_number) 和 frontend_host(frontend) 生成。


get_principal 函数


check_frontend_length 是检查 frontend 长度,不能超过 255 字节。


计算身份用到了 calculate_seed 和 der_encode_canister_sig_key 两个函数,如下:


calculate_seed 和 der_encode_canister_sig_key 函数


这里没有特别要说的,略过。



关于 Delegation 实现逻辑


在 DApp 前端,选择 II 登陆的时候,前端会生成一对私钥和公钥,这个私钥和公钥是临时的,有过期时间。


然后会跳转到 identity.ic0.app ,并显示 DApp 的 URL,点击 Proceed,会进行 Delegation 的处理,完成后,跳转回 DApp URL。

II 跳转确认


在点击 Proceed 的时候前端会调用 prepare_delegation 和 get_delegation 两个函数。


Delegation 数据结构


prepare_delegation 函数


get_delegation 函数


Delegation 的逻辑是在 prepare_delegation 中,get_delegation 只是前端重新获取了一次。


前端传给 prepare_delegation 的参数主要是:


  1. user_number:也就是 Anchor

  2. frontend:DApp URL

  3. session_key: 前端生成的临时公钥

  4. max_time_to_live: Delegation 过期时间,由前端指定,但是服务端有限制,最大 8 天(MAX_EXPIRATION_PERIOD_NS)


prepare_delegation 对这四者做一个签名,并保存在服务端。


prepare_delegation 还会返回通过 user_number(Anchor) 和 frontend 计算出来的公钥,它代表着登陆到 DApp 的身份,前端会拿到这个身份,注意,这个身份和前端临时生成的私钥和公钥没有关系。


前端调用 get_delegation 之后,就可以获得 Delegation 和它的签名了。


所以,在 II 跳转回 DApp URL 之后,前端就可以获取到身份和 Delegation:


  1. 身份,代表着用户登录到 DApp 的「分身」

  2. Delegation 代表着经过设备授权的可以与 DApp 交互的权限


下面两张图是前端存储里保存的身份和 Delegation 例子。


前端的身份


前端的 Delegation



总 结


附一张 II 的架构图:


II 架构图


另外下面这张图描述了登录 DApp 的流程:


II 登陆 DApp 流程图


最后,II 的代码地址,👇

https://github.com/dfinity/internet-identity



作者:tinywateer

原文链接:

https://mirror.xyz/0xFd007bb46C47D8600C139E34Df9DfceC86F0B319/EJDZKiQI7wF9hnSKxBTwlO-ZEX75BnjHBE4qGB5FThI





小助手微信号

入群请添加

联系我们

ICPL Twitter

https://twitter.com/icpleague_com

ICPL Medium

https://medium.com/icp-league

ICPL Telegram

 https://t.me/ICPL_en

ICPL 论坛

 https://icpleague.com




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存