You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中为何无法对psa_crypto的Result使用anyhow::Context?

问题背景

我正在尝试简化使用psa_crypto库的相关代码。
具体参考库官方文档给出的首个加密示例,示例代码如下:

use psa_crypto::types::algorithm::{Aead, AeadWithDefaultLengthTag};
use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
use psa_crypto::operations::{key_management, aead};
let alg = Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm);
let mut usage_flags: UsageFlags = Default::default();
usage_flags.set_encrypt();
let attributes = Attributes {
key_type: Type::Aes,
     bits: 0,
     lifetime: Lifetime::Volatile,
     policy: Policy {
         usage_flags,
         permitted_algorithms: alg.into(),
     },
};
psa_crypto::init().unwrap();
let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap();
let output_buffer_size = attributes.aead_encrypt_output_size(alg.into(), INPUT_DATA.len()).unwrap();
let mut output_buffer = vec![0; output_buffer_size];
let length = aead::encrypt(my_key, alg, &NONCE, &ADDITIONAL_DATA, &INPUT_DATA, &mut output_buffer).unwrap();
output_buffer.resize(length, 0);

我把上述代码放到返回anyhow::Result类型的函数中,想把所有unwrap调用替换成符合Rust惯用写法的错误处理逻辑。但尝试把第一个unwrap替换为.context("error")调用时触发编译错误,错误信息如下:

let my_key = key_management::import(attributes, None, &KEY_DATA).context("error")?;
                                                                 ^^^^^^^ method cannot be called on `Result<Id, psa_crypto::types::status::Error>` due to unsatisfied trait bounds


    |
504 | pub enum Result<T, E> {
    | --------------------- doesn't satisfy `_: anyhow::Context<Id, psa_crypto::types::status::Error>`
    |
   ::: /home/fedboz01/.cargo/registry/src/github.com-1ecc6299db9ec823/psa-crypto-0.9.1/src/types/status.rs:50:1
    |
50  | pub enum Error {
    | -------------- doesn't satisfy `_: anyhow::context::ext::StdError`
    |
    = note: the following trait bounds were not satisfied:
            `psa_crypto::types::status::Error: anyhow::context::ext::StdError`
            which is required by `Result<Id, psa_crypto::types::status::Error>: anyhow::Context<Id, psa_crypto::types::status::Error>`
报错含义

报错核心原因是anyhow::Context trait 对结果的错误类型有强制要求:错误类型必须实现标准库的std::error::Error trait,而psa_crypto::types::status::Error默认没有实现这个trait,因此无法直接在返回该错误类型的Result上调用.context()方法。

修复方案

有两种常用修复方式,根据使用场景选择即可:

  • 方案1:用map_err做错误类型转换
    在调用.context()之前,先把psa_crypto的错误转成可以被anyhow接收的类型,示例写法:
    let my_key = key_management::import(attributes, None, &KEY_DATA)
        .map_err(|e| anyhow::anyhow!(e))
        .context("导入密钥失败")?;
    
    其余所有返回psa_crypto::types::status::Error的Result都可以套用这个写法,先做错误类型转换再附加上下文。
  • 方案2:开启psa_crypto的对应feature自动实现标准错误 trait
    0.9.1版本的psa_crypto提供了可选的std feature,开启后会自动为自身的Error类型实现std::error::Error trait,直接在Cargo.toml里修改依赖配置即可:
    psa-crypto = { version = "0.9.1", features = ["std"] }
    
    开启这个feature后,不需要额外写map_err转换,就可以直接在返回psa_crypto错误的Result上调用.context()附加上下文,和最初的写法完全一致。

注意:如果项目是no_std环境,不能使用方案2,选择方案1做手动错误转换即可。


内容的提问来源于stack exchange,提问作者heapOverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:54:21