1use core::{cmp, fmt, hash};
24use std::convert::Infallible;
25
26use p256::{
27 ecdsa::{
28 signature::{Signer, Verifier},
29 Signature, SigningKey, VerifyingKey,
30 },
31 EncodedPoint,
32};
33use sec1::{DecodeEcPrivateKey, EncodeEcPrivateKey};
34use zeroize::Zeroize;
35
36use super::error::DecodingError;
37
38#[derive(Clone)]
40pub struct Keypair {
41 secret: SecretKey,
42 public: PublicKey,
43}
44
45impl Keypair {
46 #[cfg(feature = "rand")]
48 pub fn generate() -> Keypair {
49 Keypair::from(SecretKey::generate())
50 }
51
52 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
54 self.secret.sign(msg)
55 }
56
57 pub fn public(&self) -> &PublicKey {
59 &self.public
60 }
61
62 pub fn secret(&self) -> &SecretKey {
64 &self.secret
65 }
66}
67
68impl fmt::Debug for Keypair {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 f.debug_struct("Keypair")
71 .field("public", &self.public())
72 .finish()
73 }
74}
75
76impl From<SecretKey> for Keypair {
78 fn from(secret: SecretKey) -> Keypair {
79 let public = PublicKey(VerifyingKey::from(&secret.0));
80 Keypair { secret, public }
81 }
82}
83
84impl From<Keypair> for SecretKey {
86 fn from(kp: Keypair) -> SecretKey {
87 kp.secret
88 }
89}
90
91#[derive(Clone)]
93pub struct SecretKey(SigningKey);
94
95impl SecretKey {
96 #[cfg(feature = "rand")]
98 pub fn generate() -> SecretKey {
99 SecretKey(SigningKey::random(&mut rand::thread_rng()))
100 }
101
102 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
104 let signature: p256::ecdsa::DerSignature = self.0.sign(msg);
105
106 signature.as_bytes().to_owned()
107 }
108
109 pub fn to_bytes(&self) -> Vec<u8> {
111 self.0.to_bytes().to_vec()
112 }
113
114 pub fn try_from_bytes(buf: impl AsRef<[u8]>) -> Result<SecretKey, DecodingError> {
116 SigningKey::from_bytes(buf.as_ref().into())
117 .map_err(|err| DecodingError::failed_to_parse("ecdsa p256 secret key", err))
118 .map(SecretKey)
119 }
120
121 pub(crate) fn encode_der(&self) -> Vec<u8> {
123 self.0
124 .to_sec1_der()
125 .expect("Encoding to pkcs#8 format to succeed")
126 .to_bytes()
127 .to_vec()
128 }
129
130 pub(crate) fn try_decode_der(buf: &mut [u8]) -> Result<Self, DecodingError> {
132 match SigningKey::from_sec1_der(buf) {
133 Ok(key) => {
134 buf.zeroize();
135 Ok(SecretKey(key))
136 }
137 Err(e) => Err(DecodingError::failed_to_parse("ECDSA", e)),
138 }
139 }
140}
141
142impl fmt::Debug for SecretKey {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "SecretKey")
145 }
146}
147
148#[derive(Clone, Eq, PartialOrd, Ord)]
150pub struct PublicKey(VerifyingKey);
151
152impl PublicKey {
153 pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
155 let Ok(sig) = Signature::from_der(sig) else {
156 return false;
157 };
158 self.0.verify(msg, &sig).is_ok()
159 }
160
161 pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
164 let enc_pt = EncodedPoint::from_bytes(k)
165 .map_err(|e| DecodingError::failed_to_parse("ecdsa p256 encoded point", e))?;
166
167 VerifyingKey::from_encoded_point(&enc_pt)
168 .map_err(|err| DecodingError::failed_to_parse("ecdsa p256 public key", err))
169 .map(PublicKey)
170 }
171
172 pub fn to_bytes(&self) -> Vec<u8> {
175 self.0.to_encoded_point(false).as_bytes().to_owned()
176 }
177
178 pub fn encode_der(&self) -> Vec<u8> {
180 let buf = self.to_bytes();
181 Self::add_asn1_header(&buf)
182 }
183
184 pub fn try_decode_der(k: &[u8]) -> Result<PublicKey, DecodingError> {
186 let buf = Self::del_asn1_header(k).ok_or_else(|| {
187 DecodingError::failed_to_parse::<Infallible, _>(
188 "ASN.1-encoded ecdsa p256 public key",
189 None,
190 )
191 })?;
192 Self::try_from_bytes(buf)
193 }
194
195 const EC_PUBLIC_KEY_OID: [u8; 9] = [0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01];
197 const SECP_256_R1_OID: [u8; 10] = [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
199
200 fn add_asn1_header(key_buf: &[u8]) -> Vec<u8> {
202 let mut asn1_buf = vec![
204 0x30,
205 0x00,
206 0x30,
207 (Self::EC_PUBLIC_KEY_OID.len() + Self::SECP_256_R1_OID.len()) as u8,
208 ];
209 asn1_buf.extend_from_slice(&Self::EC_PUBLIC_KEY_OID);
211 asn1_buf.extend_from_slice(&Self::SECP_256_R1_OID);
212 asn1_buf.extend_from_slice(&[0x03, (key_buf.len() + 1) as u8, 0x00]);
214 asn1_buf.extend_from_slice(key_buf);
216 asn1_buf[1] = (asn1_buf.len() - 2) as u8;
218
219 asn1_buf
220 }
221
222 fn del_asn1_header(asn1_buf: &[u8]) -> Option<&[u8]> {
224 let oids_len = Self::EC_PUBLIC_KEY_OID.len() + Self::SECP_256_R1_OID.len();
225 let asn1_head = asn1_buf.get(..4)?;
226 let oids_buf = asn1_buf.get(4..4 + oids_len)?;
227 let bitstr_head = asn1_buf.get(4 + oids_len..4 + oids_len + 3)?;
228
229 if asn1_head[0] != 0x30
231 || asn1_head[2] != 0x30
232 || asn1_head[3] as usize != oids_len
233 || oids_buf[..Self::EC_PUBLIC_KEY_OID.len()] != Self::EC_PUBLIC_KEY_OID
234 || oids_buf[Self::EC_PUBLIC_KEY_OID.len()..] != Self::SECP_256_R1_OID
235 || bitstr_head[0] != 0x03
236 || bitstr_head[2] != 0x00
237 {
238 return None;
239 }
240
241 let key_len = bitstr_head[1].checked_sub(1)? as usize;
242 let key_buf = asn1_buf.get(4 + oids_len + 3..4 + oids_len + 3 + key_len)?;
243 Some(key_buf)
244 }
245}
246
247impl fmt::Debug for PublicKey {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 f.write_str("PublicKey(asn.1 uncompressed): ")?;
250 for byte in &self.encode_der() {
251 write!(f, "{byte:x}")?;
252 }
253 Ok(())
254 }
255}
256
257impl cmp::PartialEq for PublicKey {
258 fn eq(&self, other: &Self) -> bool {
259 self.to_bytes().eq(&other.to_bytes())
260 }
261}
262
263impl hash::Hash for PublicKey {
264 fn hash<H: hash::Hasher>(&self, state: &mut H) {
265 self.to_bytes().hash(state);
266 }
267}
268
269#[cfg(test)]
270mod tests {
271 use super::*;
272
273 #[test]
274 #[cfg(feature = "rand")]
275 fn sign_verify() {
276 let pair = Keypair::generate();
277 let pk = pair.public();
278
279 let msg = "hello world".as_bytes();
280 let sig = pair.sign(msg);
281 assert!(pk.verify(msg, &sig));
282
283 let mut invalid_sig = sig.clone();
284 invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
285 assert!(!pk.verify(msg, &invalid_sig));
286
287 let invalid_msg = "h3ll0 w0rld".as_bytes();
288 assert!(!pk.verify(invalid_msg, &sig));
289 }
290}