1use crate::{Algorithm, EcdsaCurve, Error, Result};
4use core::fmt;
5use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
6use sec1::consts::{U32, U48, U66};
7
8pub type EcdsaNistP256PublicKey = sec1::EncodedPoint<U32>;
10
11pub type EcdsaNistP384PublicKey = sec1::EncodedPoint<U48>;
13
14pub type EcdsaNistP521PublicKey = sec1::EncodedPoint<U66>;
16
17#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
24pub enum EcdsaPublicKey {
25 NistP256(EcdsaNistP256PublicKey),
27
28 NistP384(EcdsaNistP384PublicKey),
30
31 NistP521(EcdsaNistP521PublicKey),
33}
34
35impl EcdsaPublicKey {
36 const MAX_SIZE: usize = 133;
42
43 pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self> {
47 match bytes {
48 [tag, rest @ ..] => {
49 let point_size = match sec1::point::Tag::from_u8(*tag)? {
50 sec1::point::Tag::CompressedEvenY | sec1::point::Tag::CompressedOddY => {
51 rest.len()
52 }
53 sec1::point::Tag::Uncompressed => rest.len() / 2,
54 _ => return Err(Error::AlgorithmUnknown),
55 };
56
57 match point_size {
58 32 => Ok(Self::NistP256(EcdsaNistP256PublicKey::from_bytes(bytes)?)),
59 48 => Ok(Self::NistP384(EcdsaNistP384PublicKey::from_bytes(bytes)?)),
60 66 => Ok(Self::NistP521(EcdsaNistP521PublicKey::from_bytes(bytes)?)),
61 _ => Err(encoding::Error::Length.into()),
62 }
63 }
64 _ => Err(encoding::Error::Length.into()),
65 }
66 }
67
68 pub fn as_sec1_bytes(&self) -> &[u8] {
70 match self {
71 EcdsaPublicKey::NistP256(point) => point.as_bytes(),
72 EcdsaPublicKey::NistP384(point) => point.as_bytes(),
73 EcdsaPublicKey::NistP521(point) => point.as_bytes(),
74 }
75 }
76
77 pub fn algorithm(&self) -> Algorithm {
79 Algorithm::Ecdsa {
80 curve: self.curve(),
81 }
82 }
83
84 pub fn curve(&self) -> EcdsaCurve {
86 match self {
87 EcdsaPublicKey::NistP256(_) => EcdsaCurve::NistP256,
88 EcdsaPublicKey::NistP384(_) => EcdsaCurve::NistP384,
89 EcdsaPublicKey::NistP521(_) => EcdsaCurve::NistP521,
90 }
91 }
92}
93
94impl AsRef<[u8]> for EcdsaPublicKey {
95 fn as_ref(&self) -> &[u8] {
96 self.as_sec1_bytes()
97 }
98}
99
100impl Decode for EcdsaPublicKey {
101 type Error = Error;
102
103 fn decode(reader: &mut impl Reader) -> Result<Self> {
104 let curve = EcdsaCurve::decode(reader)?;
105
106 let mut buf = [0u8; Self::MAX_SIZE];
107 let key = Self::from_sec1_bytes(reader.read_byten(&mut buf)?)?;
108
109 if key.curve() == curve {
110 Ok(key)
111 } else {
112 Err(Error::AlgorithmUnknown)
113 }
114 }
115}
116
117impl Encode for EcdsaPublicKey {
118 fn encoded_len(&self) -> encoding::Result<usize> {
119 [
120 self.curve().encoded_len()?,
121 4, self.as_ref().len(),
123 ]
124 .checked_sum()
125 }
126
127 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
128 self.curve().encode(writer)?;
129 self.as_ref().encode(writer)?;
130 Ok(())
131 }
132}
133
134impl fmt::Display for EcdsaPublicKey {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(f, "{self:X}")
137 }
138}
139
140impl fmt::LowerHex for EcdsaPublicKey {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 for byte in self.as_sec1_bytes() {
143 write!(f, "{byte:02x}")?;
144 }
145 Ok(())
146 }
147}
148
149impl fmt::UpperHex for EcdsaPublicKey {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 for byte in self.as_sec1_bytes() {
152 write!(f, "{byte:02X}")?;
153 }
154 Ok(())
155 }
156}
157
158macro_rules! impl_ecdsa_for_curve {
159 ($krate:ident, $feature:expr, $curve:ident) => {
160 #[cfg(feature = $feature)]
161 impl TryFrom<EcdsaPublicKey> for $krate::ecdsa::VerifyingKey {
162 type Error = Error;
163
164 fn try_from(key: EcdsaPublicKey) -> Result<$krate::ecdsa::VerifyingKey> {
165 $krate::ecdsa::VerifyingKey::try_from(&key)
166 }
167 }
168
169 #[cfg(feature = $feature)]
170 impl TryFrom<&EcdsaPublicKey> for $krate::ecdsa::VerifyingKey {
171 type Error = Error;
172
173 fn try_from(public_key: &EcdsaPublicKey) -> Result<$krate::ecdsa::VerifyingKey> {
174 match public_key {
175 EcdsaPublicKey::$curve(key) => {
176 $krate::ecdsa::VerifyingKey::from_encoded_point(key)
177 .map_err(|_| Error::Crypto)
178 }
179 _ => Err(Error::AlgorithmUnknown),
180 }
181 }
182 }
183
184 #[cfg(feature = $feature)]
185 impl From<$krate::ecdsa::VerifyingKey> for EcdsaPublicKey {
186 fn from(key: $krate::ecdsa::VerifyingKey) -> EcdsaPublicKey {
187 EcdsaPublicKey::from(&key)
188 }
189 }
190
191 #[cfg(feature = $feature)]
192 impl From<&$krate::ecdsa::VerifyingKey> for EcdsaPublicKey {
193 fn from(key: &$krate::ecdsa::VerifyingKey) -> EcdsaPublicKey {
194 EcdsaPublicKey::$curve(key.to_encoded_point(false))
195 }
196 }
197 };
198}
199
200impl_ecdsa_for_curve!(p256, "p256", NistP256);
201impl_ecdsa_for_curve!(p384, "p384", NistP384);
202impl_ecdsa_for_curve!(p521, "p521", NistP521);