wip
1#![cfg_attr(target_arch = "riscv32", no_std, no_main)]
2
3extern crate alloc;
4
5use alloc::{string::ToString, vec::Vec};
6use common::message::{Request, Response};
7use sdk::{
8 App,
9 curve::{Curve, EcfpPrivateKey, Secp256k1, ToPublicKey},
10};
11
12sdk::bootstrap!();
13
14#[cfg(not(test))]
15fn display_key(pubkey: &[u8], index: u32) -> bool {
16 use alloc::string::ToString;
17 use base58::ToBase58;
18 use sdk::ux::TagValue;
19
20 let did_key = alloc::format!("did:key:z{}", pubkey.to_base58());
21
22 sdk::ux::review_pairs(
23 "Verify Atproto DID key",
24 "",
25 &[TagValue {
26 tag: "Index".into(),
27 value: index.to_string(),
28 }],
29 &did_key,
30 "Confirm",
31 false,
32 )
33}
34
35#[cfg(test)]
36fn display_key(pubkey: &[u8], index: u32) -> bool {
37 true
38}
39
40pub fn get_did_key(index: u32, display: bool) -> Result<Response, &'static str> {
41 if index > 256 {
42 return Err("Derivation path is too long");
43 }
44
45 let hd_node = sdk::curve::Secp256k1::derive_hd_node(&[index])?;
46 let privkey: EcfpPrivateKey<Secp256k1, 32> = EcfpPrivateKey::new(*hd_node.privkey);
47 let pubkey = privkey.to_public_key();
48 let uncompressed_pubkey = pubkey.as_ref().to_bytes();
49
50 let mut key = Vec::with_capacity(34);
51 key.push(0xE7);
52 key.push(uncompressed_pubkey[64] % 2 + 0x02);
53 key.extend_from_slice(&uncompressed_pubkey[1..33]);
54
55 if display && !display_key(&key, index) {
56 return Err("Rejected by the user");
57 }
58
59 Ok(Response::DidKey(key))
60}
61
62fn process(_app: &mut App, request: &[u8]) -> Vec<u8> {
63 let Ok(request) = postcard::from_bytes::<Request>(request) else {
64 return postcard::to_allocvec(&Response::Error("Invalid request".to_string())).unwrap();
65 };
66 let response = match request {
67 Request::Exit => sdk::exit(0),
68 Request::GetDidKey { index, display } => {
69 get_did_key(index, display).unwrap_or_else(|e| Response::Error(e.to_string()))
70 }
71 };
72 postcard::to_allocvec(&response).unwrap()
73}
74
75pub fn main() {
76 App::new(process).run()
77}