4个版本

0.1.4 2024年5月28日
0.1.3 2024年5月27日
0.1.2 2024年5月11日
0.1.1 2024年4月26日

#137身份验证

每月 36次下载

MIT/Apache

140KB
1.5K SLoC

智能-IDRust客户端

⚡ 由 ⚡ 维护

Smart-ID客户端是一个用于与Smart-ID API交互的Rust库。它提供了一个简单的接口,用于使用Smart-ID进行移动身份验证和移动数字签名。

简介

该库可用于轻松集成Smart-ID API。它提供了一个简单的接口,用于使用Smart-ID进行移动身份验证和移动数字签名。还提供了一些额外的实用工具,以方便与Smart-ID API集成。

  • 生成摘要和计算验证码
  • 辅助结构体
  • 与移动端用户的交互

状态

测试版 - 正在开发中!

文档

Smart-ID文档

演示环境

演示参数

构建

cargo build

示例

cargo run --example smart_id_client

测试

cargo test

文档

cargo doc --no-deps --open

示例客户端

请查看示例文件夹中的简单示例客户端。要创建SmartID账户,请下载应用程序: SmartID应用程序

示例应用程序涵盖了以下用例:

  • 验证证书存在
  • SmartID身份验证
  • SmartID数字签名

该示例使用MOCK ID来模拟SmartID用户。

cargo run --example smart_id_client

配置

SmartID配置可以从环境变量中加载

/// Get default Config (from environment variables)
let cfg = get_config_from_env();

或使用构建器模式

/// Config Builder
let cfg = SmartIDConfigBuilder::new().url("https://sid.demo.sk.ee/smart-id-rp/v2").build().expect("Error building config");

验证证书存在

要检查用户是否已加入,请使用 get_certificate_by_semantic_identifier

async fn uc_get_certificate_choice(cfg: &SmartIDConfig) -> Result<()> {

    /// Create the semantic identifier
    let sem_id = SemanticsIdentifier::new_from_enum_mock(IdentityType::PNO, CountryCode::BE);

    /// Verify if a certificate exists for given id
    let res = get_certificate_by_semantic_identifier(&cfg, sem_id).await;
    match res {
        Ok(r) => {
            let cert = validate_response_success(r).map(|res| res.cert.unwrap().value.unwrap())?;
            info!("Smart ID Certificate {:#?}", cert);
            Ok(())
        }
        Err(_) => Err(anyhow::anyhow!("Error getting certificate"))
    }
}

SmartID身份验证

要验证用户,请使用 authenticate_by_semantic_identifier

async fn uc_authenticate_by_semantic_identifier(cfg: &SmartIDConfig) -> Result<()> {
    /// Create the semantic identifier
    let sem_id = SemanticsIdentifier::new_from_enum_mock(IdentityType::PNO, CountryCode::BE);

    /// Define interactions
    let interactions: Vec<Interaction> = vec![Interaction::diplay_text_and_pin("Authenticate to Application: ReadMyCards")];

    /// Create hash
    let hash_type = HashType::SHA256;
    let hash = sha_digest("This is a test string".to_string().into_bytes(), &hash_type)?;
    let b64_hash =  base64::engine::general_purpose::STANDARD.encode(hash.as_ref());
    let verification_code_for_user = generate_verification_number(hash.as_ref().to_vec())?;
    info!("Verification code for user: {}", verification_code_for_user);

    /// Ask user for authentication
    let res = authenticate_by_semantic_identifier(&cfg, sem_id, interactions, b64_hash, hash_type).await;

    match res {
        Ok(r) => {
            let session_result = validate_response_success(r).map(|res| res.result)?;
            info!("Smart ID Authentication result {:#?}", session_result);
            Ok(())
        }
        Err(_) => Err(anyhow::anyhow!("Error during authentication"))
    }
}

SmartID数字签名

要作为用户签名文档,请使用 sign_by_semantic_identifier

async fn uc_sign_by_semantic_identifier(cfg: &SmartIDConfig) -> Result<()> {
    /// Create the semantic identifier
    let sem_id = SemanticsIdentifier::new_from_enum_mock(IdentityType::PNO, CountryCode::BE);

    /// Define interactions
    let interactions: Vec<Interaction> = vec![Interaction::confirmation_message("Are you sure to sign document: something.pdf?"), Interaction::diplay_text_and_pin("Sign using ReadMyCards")];

    /// Create hash
    let hash_type = HashType::SHA256;
    let hash = sha_digest("This is a test string".to_string().into_bytes(), &hash_type)?;
    let b64_hash =  base64::engine::general_purpose::STANDARD.encode(hash.as_ref());

    /// Create verification cod
    let verification_code_for_user = generate_verification_number(hash.as_ref().to_vec())?;
    info!("Verification code for user: {}", verification_code_for_user);

    /// Ask user to sign
    let res = sign_by_semantic_identifier(&cfg, sem_id, interactions, b64_hash, hash_type).await;
    match res {
        Ok(r) => {
            match validate_response_success(r).map(|res| res.signature)? {
                None => {
                    warn!("No signature");
                    Ok(())
                }
                Some(signature) => {
                    info!("Smart ID signature result {:#?}", signature);
                    Ok(())
                }
            }
        }
        Err(_) => Err(anyhow::anyhow!("Error signing digest"))
    }
}

依赖关系

~20–32MB
~599K SLoC