Threshold ECDSA Signatures

Hey @senior.joinu, I was able to get the master ECDSA public keys from mainnet:

let production_public_key = "02121bc3a5c38f38ca76487c72007ebbfd34bc6c4cb80a671655aa94585bbd0a02";
let test_public_key = "02f9ac345f6be6db51e1c5612cddb59e72c3d0d493c994d12035cf13257e3b1fa7"

You can derive any canister key from the master key using something along these lines:

fn derive_public_key(
    canister_id: Principal,
    derivation_path: Vec<Vec<u8>>,
) -> Result<EcdsaPublicKeyResponse, String> {
    use ic_crypto_extended_bip32::{
        DerivationIndex, DerivationPath,
    };
    let master_key_hex = "02121bc3a5c38f38ca76487c72007ebbfd34bc6c4cb80a671655aa94585bbd0a02";

    let master_key = hex::decode(master_key_hex).expect("Master key could not be deserialized");
    let master_chain_code = [0u8; 32];
    

    let mut path = vec![];
    let derivation_index = DerivationIndex(canister_id.as_slice().to_vec());
    path.push(derivation_index);

    for index in derivation_path {
        path.push(DerivationIndex(index));
    }
    let derivation_path = DerivationPath::new(path);

    let res = derivation_path
        .key_derivation(
            &master_key,
            &master_chain_code,
        )
        .map_err(|err| format!("Internal Error: {:?}", err))?;

    Ok(EcdsaPublicKeyResponse {
        public_key: res.derived_public_key,
        chain_code: res.derived_chain_code,
    })
}

I also wrote a small test to verify the derivation of the ckbtc master public key and chain-code (which you could see from the first lines of the logs in here):

#[test]
fn check_ckbtc_key_locally() {
    let ckbtc_minter_id = Principal::from_str("mqygn-kiaaa-aaaar-qaadq-cai").unwrap();
    let ckbtc_public_key = "0222047a81d4f8a067031c89273d241b79a5a007c04dfaf36d07963db0b99097eb";
    let ckbtc_chain_code = "821aebb643bd97d319d2fd0b2e483d4e7de2ea9039ff67568b693e6abc14a03b";

    let derived_key = derive_public_key(ckbtc_minter_id, vec![]);

    assert!(derived_key.is_ok(), "{}", derived_key.unwrap_err());
    let derived_key = derived_key.unwrap();

    assert_eq!(hex::encode(derived_key.public_key), ckbtc_public_key);
    assert_eq!(hex::encode(derived_key.chain_code), ckbtc_chain_code);
}

Hope this helps!

Andrea

8 Likes