affinidi_encoding/
multicodec.rs1use crate::EncodingError;
9use serde::{Deserialize, Serialize};
10use zeroize::{Zeroize, ZeroizeOnDrop};
11
12pub const ED25519_PUB: u64 = 0xed;
17pub const ED25519_PRIV: u64 = 0x1300;
18pub const X25519_PUB: u64 = 0xec;
19pub const X25519_PRIV: u64 = 0x1302;
20pub const SECP256K1_PUB: u64 = 0xe7;
21pub const SECP256K1_PRIV: u64 = 0x1301;
22pub const P256_PUB: u64 = 0x1200;
23pub const P256_PRIV: u64 = 0x1306;
24pub const P384_PUB: u64 = 0x1201;
25pub const P384_PRIV: u64 = 0x1307;
26pub const P521_PUB: u64 = 0x1202;
27pub const P521_PRIV: u64 = 0x1308;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
31pub enum Codec {
32 Ed25519Pub,
33 Ed25519Priv,
34 X25519Pub,
35 X25519Priv,
36 Secp256k1Pub,
37 Secp256k1Priv,
38 P256Pub,
39 P256Priv,
40 P384Pub,
41 P384Priv,
42 P521Pub,
43 P521Priv,
44 Unknown(u64),
45}
46
47impl Codec {
48 pub fn from_u64(value: u64) -> Self {
50 match value {
51 ED25519_PUB => Codec::Ed25519Pub,
52 ED25519_PRIV => Codec::Ed25519Priv,
53 X25519_PUB => Codec::X25519Pub,
54 X25519_PRIV => Codec::X25519Priv,
55 SECP256K1_PUB => Codec::Secp256k1Pub,
56 SECP256K1_PRIV => Codec::Secp256k1Priv,
57 P256_PUB => Codec::P256Pub,
58 P256_PRIV => Codec::P256Priv,
59 P384_PUB => Codec::P384Pub,
60 P384_PRIV => Codec::P384Priv,
61 P521_PUB => Codec::P521Pub,
62 P521_PRIV => Codec::P521Priv,
63 other => Codec::Unknown(other),
64 }
65 }
66
67 pub fn to_u64(self) -> u64 {
69 match self {
70 Codec::Ed25519Pub => ED25519_PUB,
71 Codec::Ed25519Priv => ED25519_PRIV,
72 Codec::X25519Pub => X25519_PUB,
73 Codec::X25519Priv => X25519_PRIV,
74 Codec::Secp256k1Pub => SECP256K1_PUB,
75 Codec::Secp256k1Priv => SECP256K1_PRIV,
76 Codec::P256Pub => P256_PUB,
77 Codec::P256Priv => P256_PRIV,
78 Codec::P384Pub => P384_PUB,
79 Codec::P384Priv => P384_PRIV,
80 Codec::P521Pub => P521_PUB,
81 Codec::P521Priv => P521_PRIV,
82 Codec::Unknown(v) => v,
83 }
84 }
85
86 pub fn is_public(&self) -> bool {
88 matches!(
89 self,
90 Codec::Ed25519Pub
91 | Codec::X25519Pub
92 | Codec::Secp256k1Pub
93 | Codec::P256Pub
94 | Codec::P384Pub
95 | Codec::P521Pub
96 )
97 }
98
99 pub fn expected_key_length(&self) -> Option<usize> {
101 match self {
102 Codec::Ed25519Pub | Codec::Ed25519Priv => Some(32),
103 Codec::X25519Pub | Codec::X25519Priv => Some(32),
104 Codec::Secp256k1Pub => Some(33), Codec::P256Pub => Some(33), Codec::P384Pub => Some(49), Codec::P521Pub => Some(67), _ => None,
109 }
110 }
111}
112
113#[derive(Zeroize, ZeroizeOnDrop)]
115pub struct MultiEncoded([u8]);
116
117impl MultiEncoded {
118 pub fn new(bytes: &[u8]) -> Result<&Self, EncodingError> {
121 unsigned_varint::decode::u64(bytes)
122 .map_err(|e| EncodingError::InvalidMulticodec(format!("varint decode: {e}")))?;
123
124 Ok(unsafe { &*(bytes as *const [u8] as *const MultiEncoded) })
125 }
126
127 pub fn len(&self) -> usize {
129 self.0.len()
130 }
131
132 pub fn is_empty(&self) -> bool {
134 self.0.is_empty()
135 }
136
137 pub fn parts(&self) -> (u64, &[u8]) {
139 unsigned_varint::decode::u64(&self.0).unwrap()
140 }
141
142 pub fn codec(&self) -> u64 {
144 self.parts().0
145 }
146
147 pub fn codec_type(&self) -> Codec {
149 Codec::from_u64(self.codec())
150 }
151
152 pub fn data(&self) -> &[u8] {
154 self.parts().1
155 }
156
157 pub fn as_bytes(&self) -> &[u8] {
159 &self.0
160 }
161}
162
163#[derive(Clone, Zeroize, ZeroizeOnDrop)]
165pub struct MultiEncodedBuf(Vec<u8>);
166
167impl MultiEncodedBuf {
168 pub fn new(bytes: Vec<u8>) -> Result<Self, EncodingError> {
170 unsigned_varint::decode::u64(&bytes)
171 .map_err(|e| EncodingError::InvalidMulticodec(format!("varint decode: {e}")))?;
172 Ok(Self(bytes))
173 }
174
175 pub fn encode(codec: Codec, bytes: &[u8]) -> Self {
177 Self::encode_raw(codec.to_u64(), bytes)
178 }
179
180 pub fn encode_bytes(codec: u64, bytes: &[u8]) -> Self {
182 Self::encode_raw(codec, bytes)
183 }
184
185 pub fn encode_raw(codec: u64, bytes: &[u8]) -> Self {
187 let mut codec_buffer = [0u8; 10];
188 let encoded_codec = unsigned_varint::encode::u64(codec, &mut codec_buffer);
189 let mut result = Vec::with_capacity(encoded_codec.len() + bytes.len());
190 result.extend(encoded_codec);
191 result.extend(bytes);
192 Self(result)
193 }
194
195 pub fn into_bytes(self) -> Vec<u8> {
198 self.0.clone()
199 }
200
201 pub fn as_bytes(&self) -> &[u8] {
203 &self.0
204 }
205
206 pub fn as_multi_encoded(&self) -> &MultiEncoded {
208 unsafe { &*(self.0.as_slice() as *const [u8] as *const MultiEncoded) }
209 }
210}
211
212impl AsRef<MultiEncoded> for MultiEncodedBuf {
213 fn as_ref(&self) -> &MultiEncoded {
214 self.as_multi_encoded()
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221
222 #[test]
223 fn test_encode_decode_ed25519() {
224 let key_bytes = [0u8; 32];
225 let encoded = MultiEncodedBuf::encode(Codec::Ed25519Pub, &key_bytes);
226
227 let decoded = MultiEncoded::new(encoded.as_bytes()).unwrap();
228 assert_eq!(decoded.codec(), ED25519_PUB);
229 assert_eq!(decoded.codec_type(), Codec::Ed25519Pub);
230 assert_eq!(decoded.data(), &key_bytes);
231 }
232
233 #[test]
234 fn test_codec_roundtrip() {
235 for codec in [
236 Codec::Ed25519Pub,
237 Codec::X25519Pub,
238 Codec::P256Pub,
239 Codec::P384Pub,
240 ] {
241 let raw = codec.to_u64();
242 assert_eq!(Codec::from_u64(raw), codec);
243 }
244 }
245}