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}