foundation_urtypes/registry/
eckey.rs1use minicbor::{
5 data::{Tag, Type},
6 decode::Error,
7 encode::Write,
8 Decode, Decoder, Encode, Encoder,
9};
10
11#[doc(alias("crypto-eckey"))]
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct ECKey<'a> {
15 pub curve: u64,
17 pub is_private: bool,
19 pub data: &'a [u8],
21}
22
23impl<'a> ECKey<'a> {
24 pub const TAG: Tag = Tag::new(306);
26
27 pub const SECP256K1: u64 = 0;
29}
30
31impl<'b, C> Decode<'b, C> for ECKey<'b> {
32 fn decode(d: &mut Decoder<'b>, _ctx: &mut C) -> Result<Self, Error> {
33 let mut curve = Self::SECP256K1;
34 let mut is_private = false;
35 let mut data = None;
36
37 let mut len = d.map()?;
38 loop {
39 match len {
40 Some(0) => break,
41 Some(n) => len = Some(n - 1),
42 None => {
43 if d.datatype()? == Type::Break {
44 break;
45 }
46 }
47 }
48
49 match d.u32()? {
50 1 => curve = d.u64()?,
51 2 => is_private = d.bool()?,
52 3 => data = Some(d.bytes()?),
53 _ => return Err(Error::message("unknown map entry")),
54 }
55 }
56
57 Ok(Self {
58 curve,
59 is_private,
60 data: data.ok_or_else(|| Error::message("data is missing"))?,
61 })
62 }
63}
64
65impl<'a, C> Encode<C> for ECKey<'a> {
66 fn encode<W: Write>(
67 &self,
68 e: &mut Encoder<W>,
69 _ctx: &mut C,
70 ) -> Result<(), minicbor::encode::Error<W::Error>> {
71 let is_not_default_curve = self.curve != Self::SECP256K1;
72 let len = is_not_default_curve as u64 + self.is_private as u64 + 1;
73 e.map(len)?;
74
75 if is_not_default_curve {
76 e.u8(1)?.u64(self.curve)?;
77 }
78
79 if self.is_private {
80 e.u8(2)?.bool(self.is_private)?;
81 }
82
83 e.u8(3)?.bytes(self.data)?;
84
85 Ok(())
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 use foundation_test_vectors::{URVector, UR};
94
95 #[test]
96 fn test_roundtrip() {
97 let vectors = URVector::new();
98
99 for vector in vectors.iter().filter(|v| matches!(v.ur, UR::ECKey(_))) {
100 let crypto_eckey_vector = vector.ur.unwrap_eckey();
101
102 let crypto_eckey = ECKey {
103 curve: ECKey::SECP256K1,
104 is_private: crypto_eckey_vector.is_private,
105 data: &crypto_eckey_vector.data,
106 };
107
108 let cbor = minicbor::to_vec(&crypto_eckey).unwrap();
109 assert_eq!(vector.as_cbor, cbor);
110 }
111 }
112}