use ic_cose_types::cose::{kdf::derive_a256gcm_key, sha3_256};
pub fn a256gcm_key(root_secret: &[u8], derivation_path: Vec<Vec<u8>>) -> [u8; 32] {
let salt = derivation_path_to_context(&derivation_path);
derive_a256gcm_key(root_secret, Some(&salt))
}
pub fn ed25519_sign_message(
root_secret: &[u8],
derivation_path: Vec<Vec<u8>>,
msg: &[u8],
) -> [u8; 64] {
let sk = ic_ed25519::PrivateKey::generate_from_seed(root_secret);
let path = ic_ed25519::DerivationPath::new(
derivation_path
.into_iter()
.map(ic_ed25519::DerivationIndex)
.collect(),
);
let (sk, _) = sk.derive_subkey(&path);
sk.sign_message(msg)
}
pub fn ed25519_public_key(
root_secret: &[u8],
derivation_path: Vec<Vec<u8>>,
) -> ([u8; 32], [u8; 32]) {
let sk = ic_ed25519::PrivateKey::generate_from_seed(root_secret);
let path = ic_ed25519::DerivationPath::new(
derivation_path
.into_iter()
.map(ic_ed25519::DerivationIndex)
.collect(),
);
let pk = sk.public_key();
let (pk, chain_code) = pk.derive_subkey(&path);
(pk.serialize_raw(), chain_code)
}
pub fn secp256k1_sign_message_bip340(
root_secret: &[u8],
derivation_path: Vec<Vec<u8>>,
msg: &[u8],
) -> [u8; 64] {
let sk = ic_secp256k1::PrivateKey::generate_from_seed(root_secret);
let path = ic_secp256k1::DerivationPath::new(
derivation_path
.into_iter()
.map(ic_secp256k1::DerivationIndex)
.collect(),
);
let (sk, _) = sk.derive_subkey(&path);
sk.sign_message_with_bip340_no_rng(msg)
}
pub fn secp256k1_sign_message_ecdsa(
root_secret: &[u8],
derivation_path: Vec<Vec<u8>>,
msg: &[u8],
) -> [u8; 64] {
let sk = ic_secp256k1::PrivateKey::generate_from_seed(root_secret);
let path = ic_secp256k1::DerivationPath::new(
derivation_path
.into_iter()
.map(ic_secp256k1::DerivationIndex)
.collect(),
);
let (sk, _) = sk.derive_subkey(&path);
sk.sign_message_with_ecdsa(msg)
}
pub fn secp256k1_sign_digest_ecdsa(
root_secret: &[u8],
derivation_path: Vec<Vec<u8>>,
message_hash: &[u8],
) -> [u8; 64] {
let sk = ic_secp256k1::PrivateKey::generate_from_seed(root_secret);
let path = ic_secp256k1::DerivationPath::new(
derivation_path
.into_iter()
.map(ic_secp256k1::DerivationIndex)
.collect(),
);
let (sk, _) = sk.derive_subkey(&path);
sk.sign_digest_with_ecdsa(message_hash)
}
pub fn secp256k1_public_key(
root_secret: &[u8],
derivation_path: Vec<Vec<u8>>,
) -> ([u8; 33], [u8; 32]) {
let sk = ic_secp256k1::PrivateKey::generate_from_seed(root_secret);
let path = ic_secp256k1::DerivationPath::new(
derivation_path
.into_iter()
.map(ic_secp256k1::DerivationIndex)
.collect(),
);
let pk = sk.public_key();
let (pk, chain_code) = pk.derive_subkey(&path);
let pk = pk.serialize_sec1(true);
let pk: [u8; 33] = pk
.try_into()
.expect("secp256k1_public_key: invalid SEC1 public key");
(pk, chain_code)
}
fn derivation_path_to_context(derivation_path: &[Vec<u8>]) -> Vec<u8> {
let mut data = Vec::new();
for path in derivation_path {
data.extend_from_slice(path);
}
sha3_256(&data).to_vec()
}