1个不稳定版本
0.1.0 | 2023年6月16日 |
---|
#1298 在 硬件支持
每月下载量:202
在 3 crates 中使用
19KB
327 行
Ledger硬件钱包APDU特性和共享类型。
这提供了对APDU进行编码和解码的抽象,以支持与Ledger设备的交互。
APDUs必须实现[ApduBase],以及实现encdec::Encode
和encdec::Decode
(或encdec::DecodeOwned
)以支持二进制序列化,命令通过[ApduReq]提供头部信息。可以使用encdec
宏自动推导encdec::Encode
和encdec::Decode
,或者手动在现有对象/编码上实现。
提供了一个[ApduStatic]辅助器来自动实现APDU请求的[ApduReq],并提供了一个通用的[ApduError]类型,以统一APDU对象之间的序列化和反序列化错误。
示例
使用[ApduStatic]的命令APDU(无主体)
use ledger_proto::{ApduStatic, ApduError, Encode, DecodeOwned};
/// Application information request APDU
#[derive(Clone, Debug, PartialEq, Encode, DecodeOwned)]
#[encdec(error = "ApduError")]
pub struct AppInfoReq {}
/// Set CLA and INS values for [AppInfoReq]
impl ApduStatic for AppInfoReq {
/// Application Info GET APDU is class `0xb0`
const CLA: u8 = 0xb0;
/// Application Info GET APDU is instruction `0x00`
const INS: u8 = 0x01;
}
手动实现响应APDU
use ledger_proto::{ApduStatic, ApduError, Encode, Decode};
/// Example response APDU
#[derive(Clone, Debug, PartialEq)]
pub struct StringResp<'a> {
pub value: &'a str,
}
/// [Encode] implementation for [StringResp]
impl <'a> Encode for StringResp<'a> {
type Error = ApduError;
/// Fetch encoded length
fn encode_len(&self) -> Result<usize, Self::Error> {
Ok(1 + self.value.as_bytes().len())
}
/// Encode to bytes
fn encode(&self, buff: &mut [u8]) -> Result<usize, Self::Error> {
let b = self.value.as_bytes();
// Check buffer length is valid
if buff.len() < self.encode_len()?
|| b.len() > u8::MAX as usize {
return Err(ApduError::InvalidLength);
}
// Write value length
buff[0] = b.len() as u8;
// Write value
buff[1..][..b.len()]
.copy_from_slice(b);
Ok(1 + b.len())
}
}
impl <'a> Decode<'a> for StringResp<'a> {
type Output = Self;
type Error = ApduError;
fn decode(buff: &'a [u8]) -> Result<(Self::Output, usize), Self::Error> {
// Check buffer length
if buff.len() < 1 {
return Err(ApduError::InvalidLength);
}
let n = buff[0]as usize;
if n + 1 > buff.len() {
return Err(ApduError::InvalidLength);
}
// Parse string value
let s = match core::str::from_utf8(&buff[1..][..n]) {
Ok(v) => v,
Err(_) => return Err(ApduError::InvalidUtf8),
};
// Return object and parsed length
Ok((Self{ value: s}, n + 1))
}
}
有关更多示例,请参阅[apdus]模块中提供的共享APDU。
依赖关系
约2MB
约50K SLoC