alloy_signer_local/
yubi.rs1use super::LocalSigner;
4use alloy_signer::utils::raw_public_key_to_address;
5use elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint};
6use k256::{PublicKey, Secp256k1};
7use yubihsm::{
8 asymmetric::Algorithm::EcK256, ecdsa::Signer as YubiSigner, object, object::Label, Capability,
9 Client, Connector, Credentials, Domain,
10};
11
12impl LocalSigner<YubiSigner<Secp256k1>> {
13 pub fn connect(connector: Connector, credentials: Credentials, id: object::Id) -> Self {
15 let client = Client::open(connector, credentials, true).unwrap();
16 let signer = YubiSigner::create(client, id).unwrap();
17 signer.into()
18 }
19
20 pub fn new(
22 connector: Connector,
23 credentials: Credentials,
24 id: object::Id,
25 label: Label,
26 domain: Domain,
27 ) -> Self {
28 let client = Client::open(connector, credentials, true).unwrap();
29 let id = client
30 .generate_asymmetric_key(id, label, domain, Capability::SIGN_ECDSA, EcK256)
31 .unwrap();
32 let signer = YubiSigner::create(client, id).unwrap();
33 signer.into()
34 }
35
36 pub fn from_key(
38 connector: Connector,
39 credentials: Credentials,
40 id: object::Id,
41 label: Label,
42 domain: Domain,
43 key: impl Into<Vec<u8>>,
44 ) -> Self {
45 let client = Client::open(connector, credentials, true).unwrap();
46 let id = client
47 .put_asymmetric_key(id, label, domain, Capability::SIGN_ECDSA, EcK256, key)
48 .unwrap();
49 let signer = YubiSigner::create(client, id).unwrap();
50 signer.into()
51 }
52}
53
54impl From<YubiSigner<Secp256k1>> for LocalSigner<YubiSigner<Secp256k1>> {
55 fn from(credential: YubiSigner<Secp256k1>) -> Self {
56 let pubkey = PublicKey::from_encoded_point(credential.public_key()).unwrap();
58 let pubkey = pubkey.to_encoded_point(false);
59 let bytes = pubkey.as_bytes();
60 debug_assert_eq!(bytes[0], 0x04);
61 let address = raw_public_key_to_address(&bytes[1..]);
62 Self::new_with_credential(credential, address, None)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use crate::SignerSync;
70 use alloy_primitives::{address, hex};
71
72 #[test]
73 fn from_key() {
74 let key = hex::decode("2d8c44dc2dd2f0bea410e342885379192381e82d855b1b112f9b55544f1e0900")
75 .unwrap();
76
77 let connector = yubihsm::Connector::mockhsm();
78 let signer = LocalSigner::from_key(
79 connector,
80 Credentials::default(),
81 0,
82 Label::from_bytes(&[]).unwrap(),
83 Domain::at(1).unwrap(),
84 key,
85 );
86
87 let msg = "Some data";
88 let sig = signer.sign_message_sync(msg.as_bytes()).unwrap();
89 assert_eq!(sig.recover_address_from_msg(msg).unwrap(), signer.address());
90 assert_eq!(signer.address(), address!("2DE2C386082Cff9b28D62E60983856CE1139eC49"));
91 }
92
93 #[test]
94 fn new_key() {
95 let connector = yubihsm::Connector::mockhsm();
96 let signer = LocalSigner::<YubiSigner<Secp256k1>>::new(
97 connector,
98 Credentials::default(),
99 0,
100 Label::from_bytes(&[]).unwrap(),
101 Domain::at(1).unwrap(),
102 );
103
104 let msg = "Some data";
105 let sig = signer.sign_message_sync(msg.as_bytes()).unwrap();
106 assert_eq!(sig.recover_address_from_msg(msg).unwrap(), signer.address());
107 }
108}