crypto_dispatch/
multikey.rs1#![allow(clippy::needless_return)]
6
7use crate::AlgorithmError;
8use codec_multikey::encode_multikey;
9use crypto_core::Algorithm;
10
11fn compress_p256_public_key(input: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
12 #[cfg(all(feature = "native", not(all(feature = "wasm", target_arch = "wasm32"))))]
13 {
14 return crypto_p256::compress_p256(input)
15 .map_err(|_| AlgorithmError::InvalidKey(Algorithm::P256));
16 }
17
18 #[cfg(all(feature = "wasm", target_arch = "wasm32"))]
19 {
20 return crypto_p256::compress_p256(input)
21 .map_err(|_| AlgorithmError::InvalidKey(Algorithm::P256));
22 }
23
24 #[cfg(not(any(
25 all(feature = "native", not(all(feature = "wasm", target_arch = "wasm32"))),
26 all(feature = "wasm", target_arch = "wasm32")
27 )))]
28 {
29 let _ = input;
30 Err(AlgorithmError::UnsupportedAlgorithm(Algorithm::P256))
31 }
32}
33
34fn compress_p384_public_key(input: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
35 #[cfg(any(feature = "native", feature = "wasm"))]
36 {
37 return crypto_p384::compress_p384(input)
38 .map_err(|_| AlgorithmError::InvalidKey(Algorithm::P384));
39 }
40
41 #[cfg(not(any(feature = "native", feature = "wasm")))]
42 {
43 let _ = input;
44 Err(AlgorithmError::UnsupportedAlgorithm(Algorithm::P384))
45 }
46}
47
48fn compress_p521_public_key(input: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
49 #[cfg(any(feature = "native", feature = "wasm"))]
50 {
51 return crypto_p521::compress_p521(input)
52 .map_err(|_| AlgorithmError::InvalidKey(Algorithm::P521));
53 }
54
55 #[cfg(not(any(feature = "native", feature = "wasm")))]
56 {
57 let _ = input;
58 Err(AlgorithmError::UnsupportedAlgorithm(Algorithm::P521))
59 }
60}
61
62fn canonicalize_sec1_public_key(
63 alg: Algorithm,
64 public_key: &[u8],
65 compressed_len: usize,
66 uncompressed_len: usize,
67 raw_len: usize,
68 compress: fn(&[u8]) -> Result<Vec<u8>, AlgorithmError>,
69) -> Result<Vec<u8>, AlgorithmError> {
70 match public_key.len() {
71 len if len == compressed_len => Ok(public_key.to_vec()),
72 len if len == uncompressed_len => compress(public_key),
73 len if len == raw_len => {
74 let capacity = raw_len
75 .checked_add(1)
76 .ok_or(AlgorithmError::InvalidKey(alg))?;
77 let mut sec1 = Vec::with_capacity(capacity);
78 sec1.push(0x04);
79 sec1.extend_from_slice(public_key);
80 compress(&sec1)
81 }
82 _ => Err(AlgorithmError::InvalidKey(alg)),
83 }
84}
85
86pub fn public_key_to_multikey(alg: Algorithm, public_key: &[u8]) -> Result<String, AlgorithmError> {
89 let (codec, key_bytes) = match alg {
90 Algorithm::Ed25519 => ("ed25519-pub", public_key.to_vec()),
91 Algorithm::X25519 => ("x25519-pub", public_key.to_vec()),
92 Algorithm::Secp256k1 => ("secp256k1-pub", public_key.to_vec()),
93 Algorithm::P384 => (
94 "p384-pub",
95 canonicalize_sec1_public_key(
96 alg,
97 public_key,
98 crypto_p384::P384_PUBLIC_KEY_COMPRESSED_LEN,
99 crypto_p384::P384_PUBLIC_KEY_UNCOMPRESSED_LEN,
100 crypto_p384::P384_PUBLIC_KEY_RAW_LEN,
101 compress_p384_public_key,
102 )?,
103 ),
104 Algorithm::P521 => (
105 "p521-pub",
106 canonicalize_sec1_public_key(
107 alg,
108 public_key,
109 crypto_p521::P521_PUBLIC_KEY_COMPRESSED_LEN,
110 crypto_p521::P521_PUBLIC_KEY_UNCOMPRESSED_LEN,
111 crypto_p521::P521_PUBLIC_KEY_RAW_LEN,
112 compress_p521_public_key,
113 )?,
114 ),
115 Algorithm::MlDsa44 => ("mldsa-44-pub", public_key.to_vec()),
116 Algorithm::MlDsa65 => ("mldsa-65-pub", public_key.to_vec()),
117 Algorithm::MlDsa87 => ("mldsa-87-pub", public_key.to_vec()),
118 Algorithm::MlKem512 => ("mlkem-512-pub", public_key.to_vec()),
119 Algorithm::MlKem768 => ("mlkem-768-pub", public_key.to_vec()),
120 Algorithm::MlKem1024 => ("mlkem-1024-pub", public_key.to_vec()),
121 Algorithm::XWing768 | Algorithm::XWing1024 => {
122 return Err(AlgorithmError::UnsupportedAlgorithm(alg));
123 }
124
125 Algorithm::P256 => {
127 let compressed = canonicalize_sec1_public_key(
128 alg,
129 public_key,
130 33,
131 65,
132 64,
133 compress_p256_public_key,
134 )?;
135
136 ("p256-pub", compressed)
137 }
138 };
139
140 encode_multikey(codec, &key_bytes).map_err(|_| AlgorithmError::InvalidKey(alg))
141}