#solana #sign-in #message #standard #wallet #output #verify

siws

遵循 Solana 钱包标准的轻量级“通过 Solana 登录”库

3 个版本

0.0.3 2024 年 5 月 2 日
0.0.2 2024 年 4 月 30 日
0.0.1 2024 年 4 月 24 日

#2798 in 魔法豆

每月 36 次下载
用于 siws-recap

MIT 许可证

27KB
482

SIWS - Solana Rust 登录库

一个简单的 Rust 实现,遵循 CAIP-122 (登录 With X) 用于 Solana,遵循 Solana 钱包标准Phantom 钱包的登录 With Solana 协议。

安装

通过在你的项目 Cargo.toml 中将 siws crate 作为依赖项包含,可以轻松安装 SIWS。

[dependencies]
# ...other dependencies
siws = "0.0.1"
# ...other dependencies

使用方法

SIWS 暴露了两个主要结构体 - SiwsMessage 用于消息验证,和 SiwsOutput 用于登录验证。

SiwsMessage 与 Solana 钱包标准的 SolanaSignInInput 类似,而 SiwsOutputSolanaSignInOutput 类似。

使用这些,你可以验证登录请求,并验证登录消息。

你主要会想要使用 SiwsOutput 结构体,因为其主要目的是为你提供简单的验证其签名的方法。

但是,如果你希望验证 SIWS 消息(你应该这样做),你可以使用 SiwsMessage::try_fromSiwsOutputsigned_message 字段中提取它。

端到端示例

以下示例代码展示了使用 actix-webtimesiws 的完整 Rust 程序,用于接收包含 SIWS 输出的 JSON 对象,从中创建 SIWS 消息,验证签名并验证消息。

Cargo.toml:

[package]
name = "siws-server-example"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4.5.1"
siws = { path = "../../siws-rs" }
time = "0.3.36"

src/main.rs

use actix_web::{error, web, App, HttpServer, Result};
use siws::message::{SiwsMessage, ValidateOptions};
use siws::output::SiwsOutput;
use time::OffsetDateTime;

async fn validate_and_verify(output: web::Json<SiwsOutput>) -> Result<String> {
    // Read the message from output.signed_message
    let message = SiwsMessage::try_from(&output.signed_message).map_err(error::ErrorBadRequest)?;

    // Validate the message
    message
        .validate(ValidateOptions {
            domain: Some("www.exmaple.com".into()), // Ensure domain is www.example.com
            nonce: Some("1337nonce".into()), // Ensure nonce is 1337nonce
            time: Some(OffsetDateTime::now_utc()) // Validate IAT, EXP, and NBF according to current time
        })
        .map_err(error::ErrorBadRequest)?;

    output.verify().map_err(error::ErrorBadRequest)?;

    Ok(String::from("Successfully verified!"))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().route("/", web::post().to(validate_and_verify)))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

SIWS 输出 继承了 serdeSerializeDeserialize 特性,并且自动将其所有字段重命名为 camelCase 以简化 Solana 钱包支持。

使用 SIWS 输出验证登录

每当您有 SIWS 输出时,只需调用其 verify 方法即可验证其签名。您可以通过解析 JSON 字符串来构建 SIWS 输出。

有关详细信息,请参阅 tests/integration_tests.rs

fn verify_from_json_message() -> Result<(), VerifyError> {
    let json = include_str!("test_message.json");

    let output: SiwsOutput = serde_json::from_str(json).unwrap();

    output.verify()?; // Result<(), VerifyError>

    Ok(())
}

验证 SIWS 消息

从前面的示例中,如果您想同时验证 SIWS 消息与特定域、nonce 或时间,可以执行以下操作

let message = SiwsMessage::try_from(&output.signed_message).map_err(error::ErrorBadRequest)?;

message.validate(ValidateOptions {
  ...
})?; // Result<(), ValidateError>

SIWS 消息

SiwsMessage 结构体用于将 SIWS 消息序列化和反序列化为其 ABNF 形式。还实现了额外的方法来支持从 &Vec<u8>&[u8] 解析它,因为 Solana 钱包签名的消息通常作为 UTF-8 字节序列。

从字符串解析 SIWS 消息

您可以从任何符合其 指定 ABNF 的字符串解析 SIWS 消息

fn example_from_str() -> Result<(), ParseError> {
    let msg = SiwsMessage::from_str(
        "\
        www.example.com wants you to sign in with your Solana account:\n\
        BSmWDgE9ex6dZYbiTsJGcwMEgFp8q4aWh92hdErQPeVW\n\
        \n\
        This is some test statement\n\
        \n\
        URI: test_uri\n\
        Version: 1\n\
        Chain ID: mainnet\n\
        Nonce: abcdefgh\n\
        Issued At: 2024-04-24T17:19:02.991469647Z\n\
        Expiration Time: 2024-04-24T23:19:02.991482123Z\n\
        Not Before: 2024-04-24T18:19:02.99148447Z\n\
        Request ID: test_rid\n\
        Resources:\n\
        - https://www.example.com/test_one\n\
        - https://www.example.com/test_two\
        ",
    )?;

    // Do something with the message

    Ok(())
}

根据 ABNF 序列化 SIWS 消息

您可以通过使用 String::from 获取符合 ABNF 的 SIWS 消息字符串

let siws_message = SiwsMessage {
    domain: "www.exmaple.com".into(),
    address: "someaddress".into(),
    ..Default::default()
};

let message_string = String::from(&siws_message);

print!("{}", message_string);

贡献

此项目旨在为 Rust 开发者提供 Sign in With Solana 的基本功能。因此,它旨在保持小巧和管理。

鼓励为此存储库做出贡献。

如果您发现任何错误,请尝试克隆存储库并自行修复,然后提交包含您建议的修复的 PR。

该项目也欢迎新功能,但是功能请求应在之前通过问题进行讨论,以符合项目的极简主义性质。

安全性

此库尚未经过安全审计。

如果您或您认识的人想要审计 siws-rs,请直接联系作者。

依赖关系

~5.5MB
~103K SLoC