Skip to content

Commit

Permalink
Merge pull request #1491 from KeystoneHQ/feat/support_ada_sign_hash
Browse files Browse the repository at this point in the history
Feat/support ada sign hash
  • Loading branch information
soralit authored Dec 6, 2024
2 parents 8b63cc1 + 3ababab commit f04475b
Show file tree
Hide file tree
Showing 16 changed files with 468 additions and 24 deletions.
12 changes: 5 additions & 7 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ core2 = { version = "0.3.3", default_features = false, features = ["alloc"] }
thiserror = { version = "1.0", package = "thiserror-core", default-features = false }
rsa = { version = "0.8.2", default-features = false }
sha1 = { version = "0.10.5", default-features = false }
ur-registry = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.39" }
ur-parse-lib = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.39" }
ur-registry = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.44" }
ur-parse-lib = { git = "https://[email protected]/KeystoneHQ/keystone-sdk-rust.git", tag = "0.0.44" }
ed25519-bip32-core = { version = "0.1.1", default-features = false }
cryptoxide = "0.4"
arrayref = "0.3.6"
Expand Down
1 change: 0 additions & 1 deletion rust/apps/cardano/src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use ed25519_bip32_core::{XPrv, XPub};
use hex;
use ur_registry::cardano::cardano_delegation::CardanoDelegation;
use ur_registry::cardano::governance::CardanoVotingRegistration;
use ur_registry::crypto_key_path::CryptoKeyPath;

pub fn build_metadata_cbor(
delegations: Vec<CardanoDelegation>,
Expand Down
38 changes: 38 additions & 0 deletions rust/apps/cardano/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use cardano_serialization_lib::protocol_types::{Ed25519Signature, PublicKey, Vke
use cryptoxide::hashing::blake2b_256;
use ed25519_bip32_core::{XPrv, XPub};
use hex;
use ur_registry::crypto_key_path::CryptoKeyPath;

pub fn parse_tx(tx: Vec<u8>, context: ParseContext) -> R<ParsedCardanoTx> {
let cardano_tx = cardano_serialization_lib::protocol_types::FixedTransaction::from_bytes(tx)?;
Expand Down Expand Up @@ -50,6 +51,43 @@ pub fn sign_data(path: &String, payload: &str, icarus_master_key: XPrv) -> R<Sig
))
}

pub fn sign_tx_hash(
tx_hash: &String,
paths: &Vec<CryptoKeyPath>,
icarus_master_key: XPrv,
) -> R<Vec<u8>> {
let tx_hash = hex::decode(tx_hash).unwrap();
let mut witness_set = cardano_serialization_lib::TransactionWitnessSet::new();
let mut vkeys = cardano_serialization_lib::Vkeywitnesses::new();
for path in paths {
match keystore::algorithms::ed25519::bip32_ed25519::derive_extended_pubkey_by_xprv(
&icarus_master_key,
&path.get_path().unwrap(),
)
.map(|v| v.public_key())
.map_err(|e| CardanoError::SigningFailed(e.to_string()))
{
Ok(pubkey) => {
let signature = keystore::algorithms::ed25519::bip32_ed25519::sign_message_by_xprv(
&icarus_master_key,
&tx_hash,
&path.get_path().unwrap(),
)
.map_err(|e| CardanoError::SigningFailed(e.to_string()))?;
// construct vkeywitness
vkeys.add(&Vkeywitness::new(
&Vkey::new(&PublicKey::from_bytes(&pubkey).unwrap()),
&Ed25519Signature::from_bytes(signature.to_vec())
.map_err(|e| CardanoError::SigningFailed(e.to_string()))?,
));
}
Err(e) => return Err(e),
}
}
witness_set.set_vkeys(&vkeys);
Ok(witness_set.to_bytes())
}

pub fn sign_tx(tx: Vec<u8>, context: ParseContext, icarus_master_key: XPrv) -> R<Vec<u8>> {
let cardano_tx = cardano_serialization_lib::protocol_types::FixedTransaction::from_bytes(tx)?;
let hash = blake2b_256(cardano_tx.raw_body().as_ref());
Expand Down
76 changes: 71 additions & 5 deletions rust/rust_c/src/cardano/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

extern crate alloc;

use alloc::string::{String, ToString};
use alloc::{format, slice};
use alloc::{
string::{String, ToString},
vec,
};

use alloc::vec::Vec;
use app_cardano::address::derive_xpub_from_xpub;
Expand All @@ -16,13 +19,14 @@ use core::str::FromStr;
use cty::c_char;
use ed25519_bip32_core::XPrv;
use hex;
use structs::DisplayCardanoSignTxHash;

use ur_registry::cardano::cardano_catalyst_signature::CardanoCatalystSignature;
use ur_registry::cardano::cardano_catalyst_voting_registration::CardanoCatalystVotingRegistrationRequest;

use ur_registry::cardano::cardano_sign_data_request::CardanoSignDataRequest;
use ur_registry::cardano::cardano_sign_data_signature::CardanoSignDataSignature;
use ur_registry::cardano::cardano_sign_request::CardanoSignRequest;
use ur_registry::cardano::cardano_sign_tx_hash_request::CardanoSignTxHashRequest;
use ur_registry::cardano::cardano_signature::CardanoSignature;
use ur_registry::crypto_key_path::CryptoKeyPath;

Expand Down Expand Up @@ -196,6 +200,43 @@ pub extern "C" fn cardano_check_tx(
Err(e) => TransactionCheckResult::from(e).c_ptr(),
}
}
#[no_mangle]
pub extern "C" fn cardano_check_tx_hash(
ptr: PtrUR,
master_fingerprint: PtrBytes,
) -> PtrT<TransactionCheckResult> {
let cardano_sign_tx_hash_reqeust = extract_ptr_with_type!(ptr, CardanoSignTxHashRequest);
let expected_mfp = unsafe { core::slice::from_raw_parts(master_fingerprint, 4) };
// check mfp
let paths = cardano_sign_tx_hash_reqeust.get_paths();
for path in paths {
let mfp = path.get_source_fingerprint();
if let Some(mfp) = mfp {
if hex::encode(mfp) != hex::encode(expected_mfp) {
return TransactionCheckResult::from(RustCError::MasterFingerprintMismatch).c_ptr();
}
}
}
TransactionCheckResult::new().c_ptr()
}

#[no_mangle]
pub extern "C" fn cardano_parse_sign_tx_hash(
ptr: PtrUR,
) -> PtrT<TransactionParseResult<DisplayCardanoSignTxHash>> {
let sign_hash_request = extract_ptr_with_type!(ptr, CardanoSignTxHashRequest);
let message = sign_hash_request.get_tx_hash();
let crypto_key_paths = sign_hash_request.get_paths();
let paths = crypto_key_paths
.iter()
.map(|v| v.get_path())
.collect::<Option<Vec<String>>>()
.unwrap_or(vec![]);
let address_list = sign_hash_request.get_address_list();
let network = "Cardano".to_string();
let result = DisplayCardanoSignTxHash::new(network, paths, message, address_list);
TransactionParseResult::success(result.c_ptr()).c_ptr()
}

#[no_mangle]
pub extern "C" fn cardano_get_path(ptr: PtrUR) -> Ptr<SimpleResponse<c_char>> {
Expand Down Expand Up @@ -444,6 +485,7 @@ pub extern "C" fn cardano_sign_tx_with_ledger_bitbox02(
cardano_xpub: PtrString,
mnemonic: PtrString,
passphrase: PtrString,
enable_blind_sign: bool,
) -> PtrT<UREncodeResult> {
let mnemonic = recover_c_char(mnemonic);
let passphrase = recover_c_char(passphrase);
Expand All @@ -452,10 +494,13 @@ pub extern "C" fn cardano_sign_tx_with_ledger_bitbox02(
passphrase.as_bytes(),
mnemonic,
);

match master_key {
Ok(master_key) => {
cardano_sign_tx_by_icarus(ptr, master_fingerprint, cardano_xpub, master_key)
if enable_blind_sign {
cardano_sign_tx_hash_by_icarus(ptr, master_key)
} else {
cardano_sign_tx_by_icarus(ptr, master_fingerprint, cardano_xpub, master_key)
}
}
Err(e) => UREncodeResult::from(e).c_ptr(),
}
Expand All @@ -469,11 +514,32 @@ pub extern "C" fn cardano_sign_tx(
entropy: PtrBytes,
entropy_len: u32,
passphrase: PtrString,
enable_blind_sign: bool,
) -> PtrT<UREncodeResult> {
let entropy = unsafe { alloc::slice::from_raw_parts(entropy, entropy_len as usize) };
let passphrase = recover_c_char(passphrase);
let icarus_master_key = calc_icarus_master_key(entropy, passphrase.as_bytes());
cardano_sign_tx_by_icarus(ptr, master_fingerprint, cardano_xpub, icarus_master_key)
if enable_blind_sign {
cardano_sign_tx_hash_by_icarus(ptr, icarus_master_key)
} else {
cardano_sign_tx_by_icarus(ptr, master_fingerprint, cardano_xpub, icarus_master_key)
}
}

fn cardano_sign_tx_hash_by_icarus(ptr: PtrUR, icarus_master_key: XPrv) -> PtrT<UREncodeResult> {
let cardano_sign_tx_hash_request = extract_ptr_with_type!(ptr, CardanoSignTxHashRequest);
let tx_hash = cardano_sign_tx_hash_request.get_tx_hash();
let paths = cardano_sign_tx_hash_request.get_paths();
let sign_result = app_cardano::transaction::sign_tx_hash(&tx_hash, &paths, icarus_master_key);
match sign_result {
Ok(v) => UREncodeResult::encode(
v,
CARDANO_SIGNATURE.get_type(),
FRAGMENT_MAX_LENGTH_DEFAULT.clone(),
)
.c_ptr(),
Err(e) => UREncodeResult::from(e).c_ptr(),
}
}

fn cardano_sign_tx_by_icarus(
Expand Down
43 changes: 42 additions & 1 deletion rust/rust_c/src/cardano/src/structs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloc::boxed::Box;
use alloc::string::ToString;
use alloc::vec::Vec;
use alloc::{boxed::Box, string::String};
use app_cardano::structs::{
CardanoCertificate, CardanoFrom, CardanoTo, CardanoWithdrawal, ParsedCardanoSignData,
ParsedCardanoTx, VotingProcedure, VotingProposal,
Expand Down Expand Up @@ -119,13 +119,45 @@ pub struct DisplayCardanoWithdrawal {
address: PtrString,
amount: PtrString,
}
#[repr(C)]
pub struct DisplayCardanoSignTxHash {
pub network: PtrString,
pub path: Ptr<VecFFI<PtrString>>,
pub tx_hash: PtrString,
pub address_list: Ptr<VecFFI<PtrString>>,
}

impl DisplayCardanoSignTxHash {
pub fn new(
network: String,
path: Vec<String>,
tx_hash: String,
address_list: Vec<String>,
) -> Self {
Self {
network: convert_c_char(network),
path: VecFFI::from(path.iter().map(|v| convert_c_char(v.clone())).collect_vec())
.c_ptr(),
tx_hash: convert_c_char(tx_hash),
address_list: VecFFI::from(
address_list
.iter()
.map(|v| convert_c_char(v.clone()))
.collect_vec(),
)
.c_ptr(),
}
}
}

impl_c_ptrs!(DisplayCardanoTx);

impl_c_ptrs!(DisplayCardanoCatalyst);

impl_c_ptrs!(DisplayCardanoSignData);

impl_c_ptrs!(DisplayCardanoSignTxHash);

impl Free for DisplayCardanoSignData {
fn free(&self) {
free_str_ptr!(self.payload);
Expand All @@ -144,6 +176,15 @@ impl Free for DisplayCardanoCatalyst {
}
}

impl Free for DisplayCardanoSignTxHash {
fn free(&self) {
free_str_ptr!(self.network);
free_vec!(self.path);
free_str_ptr!(self.tx_hash);
free_vec!(self.address_list);
}
}

impl Free for DisplayCardanoTx {
fn free(&self) {
unsafe {
Expand Down
Loading

0 comments on commit f04475b

Please sign in to comment.