identity_jose/jwk/conversion/
from_jwk.rs1use crate::error::Error;
5use crate::jwk::Jwk;
6use crate::jwk::JwkParams;
7use crate::jwk::JwkParamsEc;
8use crate::jwu;
9use anyhow::anyhow;
10use anyhow::Context as _;
11use fastcrypto::ed25519::Ed25519KeyPair;
12use fastcrypto::ed25519::Ed25519PublicKey;
13use fastcrypto::secp256k1::Secp256k1KeyPair;
14use fastcrypto::secp256r1::Secp256r1KeyPair;
15use iota_interaction::types::crypto::IotaKeyPair;
16use iota_interaction::types::crypto::PublicKey;
17use iota_interaction::types::crypto::SignatureScheme as IotaSignatureScheme;
18
19use super::ed25519;
20use super::secp256k1;
21use super::secp256r1;
22
23pub trait FromJwk: Sized {
25 type Error;
27
28 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error>;
30}
31
32impl FromJwk for IotaKeyPair {
33 type Error = Error;
34
35 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error> {
36 let maybe_ed22519 = Ed25519KeyPair::from_jwk(jwk).map(IotaKeyPair::from);
37 let maybe_secp256r1 = Secp256r1KeyPair::from_jwk(jwk).map(IotaKeyPair::from);
38 let maybe_secp256k1 = Secp256k1KeyPair::from_jwk(jwk).map(IotaKeyPair::from);
39
40 maybe_ed22519
41 .or(maybe_secp256k1)
42 .or(maybe_secp256r1)
43 .map_err(|err| Error::KeyConversion(err.to_string()))
44 }
45}
46
47impl FromJwk for PublicKey {
48 type Error = Error;
49
50 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error> {
51 match jwk.params() {
52 JwkParams::Okp(params) => {
53 if params.crv != "Ed25519" {
54 return Err(Error::KeyConversion(format!("unsupported key type {}", params.crv)));
55 }
56
57 jwu::decode_b64(¶ms.x)
58 .context("failed to base64 decode key")
59 .and_then(|pk_bytes| {
60 PublicKey::try_from_bytes(IotaSignatureScheme::ED25519, &pk_bytes).map_err(|e| anyhow!("{e}"))
61 })
62 .map_err(|err| Error::KeyConversion(err.to_string()))
63 }
64 JwkParams::Ec(JwkParamsEc { crv, x, y, .. }) => {
65 let pk_bytes = {
66 let mut decoded_x_bytes =
67 jwu::decode_b64(x).map_err(|e| Error::KeyConversion(format!("failed to decode b64 x parameter: {e}")))?;
68 let decoded_y_bytes =
69 jwu::decode_b64(y).map_err(|e| Error::KeyConversion(format!("failed to decode b64 y parameter: {e}")))?;
70
71 let last_y = decoded_y_bytes
73 .last()
74 .ok_or_else(|| Error::KeyConversion("y parameter should not be empty".to_string()))?;
75 if last_y % 2 == 0 {
76 decoded_x_bytes.insert(0, 2);
77 } else {
78 decoded_x_bytes.insert(0, 3);
79 }
80
81 decoded_x_bytes
82 };
83
84 if jwk.alg() == Some("ES256") || crv == "P-256" {
85 PublicKey::try_from_bytes(IotaSignatureScheme::Secp256r1, &pk_bytes)
86 .map_err(|e| Error::KeyConversion(format!("not a secp256r1 key: {e}")))
87 } else if jwk.alg() == Some("ES256K") || crv == "K-256" || crv == "secp256k1" {
88 PublicKey::try_from_bytes(IotaSignatureScheme::Secp256k1, &pk_bytes)
89 .map_err(|e| Error::KeyConversion(format!("not a secp256k1 key: {e}")))
90 } else {
91 Err(Error::KeyError("invalid EC key"))
92 }
93 }
94 _ => Err(Error::KeyConversion("unsupported key".to_string())),
95 }
96 }
97}
98
99impl FromJwk for Ed25519KeyPair {
100 type Error = Error;
101
102 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error> {
103 ed25519::jwk_to_keypair(jwk).map_err(|err| Error::KeyConversion(err.to_string()))
104 }
105}
106
107impl FromJwk for Secp256r1KeyPair {
108 type Error = Error;
109
110 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error> {
111 secp256r1::jwk_to_keypair(jwk).map_err(|err| Error::KeyConversion(err.to_string()))
112 }
113}
114
115impl FromJwk for Secp256k1KeyPair {
116 type Error = Error;
117
118 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error> {
119 secp256k1::jwk_to_keypair(jwk).map_err(|err| Error::KeyConversion(err.to_string()))
120 }
121}
122
123impl FromJwk for Ed25519PublicKey {
124 type Error = Error;
125
126 fn from_jwk(jwk: &Jwk) -> Result<Self, Self::Error> {
127 ed25519::from_public_jwk(jwk).map_err(|err| Error::KeyConversion(err.to_string()))
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::FromJwk;
134 use crate::jwk::Jwk;
135 use crate::jwu::encode_b64;
136
137 #[derive(PartialEq)]
138 enum KeyType {
139 Private,
140 Public,
141 }
142
143 fn get_ed25519_jwk(key_type: KeyType) -> Jwk {
144 use fastcrypto::traits::KeyPair as _;
145
146 let keypair = fastcrypto::ed25519::Ed25519KeyPair::generate(&mut rand::thread_rng());
147 let mut params = crate::jwk::JwkParamsOkp::new();
148 let x = encode_b64(keypair.public().as_ref());
149 params.x = x;
150 if key_type == KeyType::Private {
151 let d = encode_b64(keypair.private().as_ref());
152 params.d = Some(d);
153 }
154 params.crv = crate::jwk::EdCurve::Ed25519.name().to_string();
155
156 Jwk::from_params(params)
157 }
158
159 fn get_secp256r1_jwk(key_type: KeyType) -> Jwk {
160 let sk = p256::SecretKey::random(&mut rand::thread_rng());
161 let jwk_string = if key_type == KeyType::Private {
162 &sk.to_jwk_string()
163 } else {
164 &sk.public_key().to_jwk_string()
165 };
166 let jwk: Jwk = serde_json::from_str(jwk_string).unwrap();
167
168 jwk
169 }
170
171 fn get_secp256k1_jwk(key_type: KeyType) -> Jwk {
172 let sk = k256::SecretKey::random(&mut rand::thread_rng());
173 let jwk_string = if key_type == KeyType::Private {
174 &sk.to_jwk_string()
175 } else {
176 &sk.public_key().to_jwk_string()
177 };
178 let jwk: Jwk = serde_json::from_str(jwk_string).unwrap();
179 dbg!(jwk_string);
180
181 jwk
182 }
183
184 #[test]
185 fn can_convert_from_jwk_to_ed22519_iota_keypair() {
186 let jwk = get_ed25519_jwk(KeyType::Private);
187 let result = iota_interaction::types::crypto::IotaKeyPair::from_jwk(&jwk);
188
189 assert!(result.is_ok());
190 }
191
192 #[test]
193 fn can_convert_from_jwk_to_ecp256r1_iota_keypair() {
194 let jwk = get_secp256r1_jwk(KeyType::Private);
195 let result = iota_interaction::types::crypto::IotaKeyPair::from_jwk(&jwk);
196 dbg!(&result);
197
198 assert!(result.is_ok());
199 }
200
201 #[test]
202 fn can_convert_from_jwk_to_secp256k1_iota_keypair() {
203 let jwk = get_secp256k1_jwk(KeyType::Private);
204 let result = iota_interaction::types::crypto::IotaKeyPair::from_jwk(&jwk);
205 dbg!(&result);
206
207 assert!(result.is_ok());
208 }
209
210 #[test]
211 fn can_convert_from_octet_keypair_jwk_to_iota_public_key() {
212 let jwk = get_ed25519_jwk(KeyType::Public);
213 let result = iota_interaction::types::crypto::PublicKey::from_jwk(&jwk);
214
215 assert!(result.is_ok());
216 }
217
218 #[test]
219 fn can_convert_from_secp256r1_jwk_to_iota_public_key() {
220 let jwk = get_secp256r1_jwk(KeyType::Public);
221 let result = iota_interaction::types::crypto::PublicKey::from_jwk(&jwk);
222
223 assert!(result.is_ok());
224 }
225
226 #[test]
227 fn can_convert_from_secp256k1_jwk_to_iota_public_key() {
228 let jwk = get_secp256k1_jwk(KeyType::Public);
229 let result = iota_interaction::types::crypto::PublicKey::from_jwk(&jwk);
230
231 assert!(result.is_ok());
232 }
233
234 #[test]
235 fn can_convert_from_jwk_to_ed25519_key_pair() {
236 let jwk = get_ed25519_jwk(KeyType::Private);
237 let result = fastcrypto::ed25519::Ed25519KeyPair::from_jwk(&jwk);
238
239 assert!(result.is_ok());
240 }
241
242 #[test]
243 fn can_convert_from_jwk_to_secp256r1_key_pair() {
244 let jwk = get_secp256r1_jwk(KeyType::Private);
245 let result = fastcrypto::secp256r1::Secp256r1KeyPair::from_jwk(&jwk);
246
247 assert!(result.is_ok());
248 }
249
250 #[test]
251 fn can_convert_from_jwk_to_secp256k1_key_pair() {
252 let jwk = get_secp256k1_jwk(KeyType::Private);
253 let result = fastcrypto::secp256k1::Secp256k1KeyPair::from_jwk(&jwk);
254
255 assert!(result.is_ok());
256 }
257
258 #[test]
259 fn can_convert_from_jwk_to_ed25519_public_key() {
260 let jwk = get_ed25519_jwk(KeyType::Public);
261 let result = fastcrypto::ed25519::Ed25519PublicKey::from_jwk(&jwk);
262
263 assert!(result.is_ok());
264 }
265}