Internet Identity(II)的设计和实现:第二篇
本期概要
在上一篇文章中,介绍了 Internet Identity(II)的设计(Internet Identity(II)的设计和实现:第一篇),这篇文章来聊聊实现逻辑和核心代码。
本文主要包含三个部分:
Anchor 和 设备管理
如何生成身份(Principal)
Delegation 实现逻辑
II 实现的函数如下:
II 的函数列表
前面部分是 Anchor 和 设备管理,get_principal 是生成身份,prepare_delegation 和 get_delegation 是 Delegation 的实现。
Anchor 和 设备管理
设备的数据结构:
设备的数据结构
DeviceData 主要包括 pubkey(公钥)、alias(别名)、credential_id(凭据,可选,用于 WebAuthN 认证)、purpose(用途)、key_type(类型)。
设备分为普通设备和用于恢复的设备:
普通设备,purpose 为 authentication,key_type 为 unknown
用于恢复的设备,purpose 为 recovery,key_type 又分为两种情况:
如果使用助记词,key_type 为 seed_phrase
如果使用安全秘钥,key_type 为 cross_platform
在第一次使用 II,创建 Anchor 时,会提示输入第一个设备名称,点击 Create 后,会调用后端的 register 函数同时创建 Anchor 以及增加第一个设备。
创建 Anchor 和第一个设备
register 函数
register 几个重要的点:
check_entry_limits 是检查一些限制,包括别名、公钥和凭据的长度限制
store.allocate_user_number() 会生成一个 Anchor,它是自增 ID,加 1 即可
然后把 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 的参数主要是:
user_number:也就是 Anchor
frontend:DApp URL
session_key: 前端生成的临时公钥
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:
身份,代表着用户登录到 DApp 的「分身」
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