1 个不稳定版本
0.0.1 | 2024 年 4 月 1 日 |
---|
#105 in #internet-computer
320KB
1.5K SLoC
ic_siws
是一个 Rust 库,它简化了将基于 Solana 钱包的认证(SIWS)集成到互联网计算机(ICP)平台上的应用程序中的过程。该库提供了从生成 SIWS 消息到创建代表身份所需的所有工具。
ic_siws
是 ic-siws 项目的组成部分。该项目的目标是增强 Solana 与互联网计算机平台之间的互操作性,使开发者能够构建利用两个平台优势的应用程序。
主要功能
- Solana 钱包登录:为 ICP 应用程序启用 Solana 钱包登录。使用任何 eth 钱包登录以生成 ICP 身份和会话。
- 会话身份唯一性:确保会话身份特定于每个应用程序的上下文,防止跨应用程序身份误用。
- 一致的代表生成:保证使用 Solana 钱包登录始终生成相同的代表,无论使用哪个客户端。
- 直接将 Solana 地址映射到代表:在当前应用程序范围内,在 Solana 地址和代表之间创建一对一的关联。
- 时间限制的会话:允许开发者为会话设置过期时间,增强安全性和控制。
此外还有
ic-siwe - ic-siws
的姊妹项目,ic-siwe
为基于以太坊的应用程序提供相同的功能。
目录
预构建 ic_siws_provider
canister
虽然 ic_siws
库可以与任何基于 Rust 的 ICP 项目集成,但使用预构建的 ic-siws-provider canister 是将 Solana 钱包认证集成到您应用程序中最简单的方法。
该罐体被设计为针对开发者的即插即用解决方案,使得将其轻松集成到现有的 ICP 应用程序中,且代码编写需求最小化。通过将预构建的 ic_siws_provider
罐体添加到 ICP 项目的 dfx.json
文件中,开发者可以快速启用基于 Solana 钱包的认证功能。该罐体通过管理 SIWS 消息的创建和验证以及处理用户会话管理来简化认证流程。
React 示例应用程序
一个使用 ic_siws_provider
罐体来演示完整登录流程的演示应用程序可在 ic-siws-react-demo-rust 找到。该演示使用来自 ic-siws
项目的另一个包,ic-use-siws-identity,这是一个 React 钩子和上下文提供程序,用于简化与启用 SIWS 的互联网计算机罐体的前端集成。
SIWS:使用 Solana 登录
“使用 Solana 登录”(SIWS)是 Solana 钱包的标准,在 Solana 生态系统中得到广泛支持。它允许用户使用他们的 Solana 钱包签署消息,以对 dapp 进行身份验证,通过标准化消息格式来简化认证流程,从而改善用户体验和安全。基于由 ERC-4361: 使用以太坊登录 建立的原则,SIWS 简化了认证流程,消除了传统连接 + 签名消息步骤的需求。
该协议的核心是 SIWS 消息,它是一个包含用户 Solana 地址和一些附加元数据的已签名消息。SIWS 消息由用户的 Solana 钱包签名,然后发送到应用程序的后端。后端验证签名和 Solana 地址,然后为用户创建一个会话。
ic_siws
实现了 Sign In with Solana 标准的大部分内容,但有几个值得注意的例外
-
nonce
- SIWS 要求每个登录消息都有一个唯一的 nonce。在此实现中,nonce 并不向登录流程添加任何额外的安全性,并且默认禁用。如果需要随机 nonce,则可以启用nonce
功能标志。当此功能启用时,nonce 使用加密安全的随机数生成器生成。 -
not-before
、request-id
、resources
- 未实现。这些字段在 SIWS 标准中标记为“可选”,目前尚未实现。
登录流程
使用 ic_siws
创建代表身份的三步过程包括以下步骤
- 准备登录
- 登录
- 获取委托
实现罐体可以根据自己的意愿实现这些步骤。然而,建议实现罐体遵循以下描述的登录流程并实现 SIWS 罐体接口。这样做确保罐体与 ic-use-siws-identity React 钩子和上下文提供程序兼容。
SIWS 罐体接口
type Address = text;
type CanisterPublicKey = PublicKey;
type PublicKey = blob;
type SessionKey = PublicKey;
type SiwsSignature = text;
type Timestamp = nat64;
type GetDelegationResponse = variant {
Ok : SignedDelegation;
Err : text;
};
type SignedDelegation = record {
delegation : Delegation;
signature : blob;
};
type Delegation = record {
pubkey : PublicKey;
expiration : Timestamp;
targets : opt vec principal;
};
type LoginResponse = variant {
Ok : LoginDetails;
Err : text;
};
type LoginDetails = record {
expiration : Timestamp;
user_canister_pubkey : CanisterPublicKey;
};
type SiwsMessage = record {
domain : text;
address : Address;
statement : text;
uri : text;
version : nat32;
chain_id : text;
nonce : text;
issued_at : nat64;
expiration_time : nat64;
};
type PrepareLoginResponse = variant {
Ok : SiwsMessage;
Err : text;
};
service : (settings_input : SettingsInput) -> {
"siws_prepare_login" : (Address) -> (PrepareLoginResponse);
"siws_login" : (SiwsSignature, Address, SessionKey) -> (LoginResponse);
"siws_get_delegation" : (Address, SessionKey, Timestamp) -> (GetDelegationResponse) query;
};
siws_prepare_login
- 前端应用程序通过调用
siws_prepare_login
方法来启动登录流程。该方法接受用户的 Solana 地址作为参数,并返回一个 SIWS 消息。前端应用程序使用 SIWS 消息提示用户使用他们的 Solana 钱包签署消息。 - 查看:
login::prepare_login
登录
- 前端应用程序在用户签名SIWS消息后调用
login
方法。该方法接受用户的Solana地址、签名和会话身份作为参数。该方法验证签名和Solana地址,并返回一个代理。 - 参见:
login::login
siws_get_delegation
- 在成功登录后,前端应用程序调用
siws_get_delegation
方法。该方法接受代理过期时间作为参数,并返回一个代理。 siws_get_delegation
方法在ic_siws
库中没有对应的函数。创建代理身份需要设置canister的认证数据。这不应该由库来完成,而应该由实现canister来完成。- 创建代理身份涉及与以下
ic_siws
函数交互:delegation::generate_seed
、delegation::create_delegation
、delegation::create_delegation_hash
、delegation::witness
、delegation::create_certified_signature
。 - 有关完整实现示例,请参阅
ic_siws_provider
canister。
登录流程如图所示
┌────────┐ ┌────────┐ ┌─────────┐
│Frontend│ │Canister│ │SolWallet│
User └───┬────┘ └───┬────┘ └────┬────┘
│ Push login button ┌┴┐ │ │
│ ────────────────────────────>│ │ │ │
│ │ │ │ │
│ │ │ siws_prepare_login(eth_address) ┌┴┐ │
│ │ │ ─────────────────────────────────────────────>│ │ │
│ │ │ └┬┘ │
│ │ │ OK, siws_message │ │
│ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │ │ │ │
│ │ │ Sign siws_message ┌┴┐
│ │ │ ──────────────────────────────────────────────────────────────────────────────────────>│ │
│ │ │ │ │ │
│ │ │ Ask user to confirm │ │ │
│ <───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ │
│ │ │ │ │ │
│ │ │ OK │ │ │
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ >│ │
│ │ │ │ └┬┘
│ │ │ OK, signature │
│ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ │ │ │ │
│ │ │────┐ │ │
│ │ │ │ Generate random session_identity │ │
│ │ │<───┘ │ │
│ │ │ │ │
│ │ │ siws_login(eth_address, │ │
│ │ │ signature, session_identity) ┌┴┐ │
│ │ │ ─────────────────────────────────────────────>│ │ │
│ │ │ │ │ │
│ │ │ │ │────┐ │
│ │ │ │ │ │ Verify signature and eth_address │
│ │ │ │ │<───┘ │
│ │ │ │ │ │
│ │ │ │ │────┐ │
│ │ │ │ │ │ Prepare delegation │
│ │ │ │ │<───┘ │
│ │ │ └┬┘ │
│ │ │ OK, canister_pubkey, delegation_expires │ │
│ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │ │ │ │
│ │ │ siws_get_delegation(delegation_expires) ┌┴┐ │
│ │ │ ─────────────────────────────────────────────>│ │ │
│ │ │ └┬┘ │
│ │ │ OK, delegation │ │
│ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │ │ │ │
│ │ │────┐ │ │
│ │ │ │ Create delegation identity │ │
│ │ │<───┘ │ │
│ └┬┘ │ │
│ OK, logged in with │ │ │
│ Principal niuiu-iuhbi...-oiu │ │ │
│ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │
User ┌───┴────┐ ┌───┴────┐ ┌────┴────┐
│Frontend│ │Canister│ │SolWallet│
└────────┘ └────────┘ └─────────┘
crate 功能
库有一个默认禁用的可选功能。
nonce
- 启用为SIWS消息生成nonces。此功能使用管理canister的种子初始化随机数生成器。然后使用随机数生成器为每个生成的SIWS消息生成唯一的nonces。nonces不会为SIWS登录流程添加任何额外的安全性,但符合SIWS标准。当此功能禁用时,nonce始终设置为十六进制编码的字符串Not in use
。
更新
有关更新的详细信息,请参阅CHANGELOG。
贡献
欢迎贡献力量。请提交您的pull请求或打开问题以提出更改或报告错误。
作者
- [email protected]
- Twitter: @kristoferlund
- Discord: kristoferkristofer
- Telegram: @kristoferkristofer
许可证
本项目采用MIT许可证。有关更多详细信息,请参阅LICENSE文件。
依赖关系
~8–18MB
~249K SLoC