1use super::error::DecodingError;
24use core::cmp;
25use core::fmt;
26use core::hash;
27use p256::{
28 ecdsa::{
29 signature::{Signer, Verifier},
30 Signature, SigningKey, VerifyingKey,
31 },
32 EncodedPoint,
33};
34use sec1::{DecodeEcPrivateKey, EncodeEcPrivateKey};
35use std::convert::Infallible;
36use zeroize::Zeroize;
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> {
163 let enc_pt = EncodedPoint::from_bytes(k)
164 .map_err(|e| DecodingError::failed_to_parse("ecdsa p256 encoded point", e))?;
165
166 VerifyingKey::from_encoded_point(&enc_pt)
167 .map_err(|err| DecodingError::failed_to_parse("ecdsa p256 public key", err))
168 .map(PublicKey)
169 }
170
171 pub fn to_bytes(&self) -> Vec<u8> {
173 self.0.to_encoded_point(false).as_bytes().to_owned()
174 }
175
176 pub fn encode_der(&self) -> Vec<u8> {
178 let buf = self.to_bytes();
179 Self::add_asn1_header(&buf)
180 }
181
182 pub fn try_decode_der(k: &[u8]) -> Result<PublicKey, DecodingError> {
184 let buf = Self::del_asn1_header(k).ok_or_else(|| {
185 DecodingError::failed_to_parse::<Infallible, _>(
186 "ASN.1-encoded ecdsa p256 public key",
187 None,
188 )
189 })?;
190 Self::try_from_bytes(buf)
191 }
192
193 const EC_PUBLIC_KEY_OID: [u8; 9] = [0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01];
195 const SECP_256_R1_OID: [u8; 10] = [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
197
198 fn add_asn1_header(key_buf: &[u8]) -> Vec<u8> {
200 let mut asn1_buf = vec![
202 0x30,
203 0x00,
204 0x30,
205 (Self::EC_PUBLIC_KEY_OID.len() + Self::SECP_256_R1_OID.len()) as u8,
206 ];
207 asn1_buf.extend_from_slice(&Self::EC_PUBLIC_KEY_OID);
209 asn1_buf.extend_from_slice(&Self::SECP_256_R1_OID);
210 asn1_buf.extend_from_slice(&[0x03, (key_buf.len() + 1) as u8, 0x00]);
212 asn1_buf.extend_from_slice(key_buf);
214 asn1_buf[1] = (asn1_buf.len() - 2) as u8;
216
217 asn1_buf
218 }
219
220 fn del_asn1_header(asn1_buf: &[u8]) -> Option<&[u8]> {
222 let oids_len = Self::EC_PUBLIC_KEY_OID.len() + Self::SECP_256_R1_OID.len();
223 let asn1_head = asn1_buf.get(..4)?;
224 let oids_buf = asn1_buf.get(4..4 + oids_len)?;
225 let bitstr_head = asn1_buf.get(4 + oids_len..4 + oids_len + 3)?;
226
227 if asn1_head[0] != 0x30
229 || asn1_head[2] != 0x30
230 || asn1_head[3] as usize != oids_len
231 || oids_buf[..Self::EC_PUBLIC_KEY_OID.len()] != Self::EC_PUBLIC_KEY_OID
232 || oids_buf[Self::EC_PUBLIC_KEY_OID.len()..] != Self::SECP_256_R1_OID
233 || bitstr_head[0] != 0x03
234 || bitstr_head[2] != 0x00
235 {
236 return None;
237 }
238
239 let key_len = bitstr_head[1].checked_sub(1)? as usize;
240 let key_buf = asn1_buf.get(4 + oids_len + 3..4 + oids_len + 3 + key_len)?;
241 Some(key_buf)
242 }
243}
244
245impl fmt::Debug for PublicKey {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 f.write_str("PublicKey(asn.1 uncompressed): ")?;
248 for byte in &self.encode_der() {
249 write!(f, "{byte:x}")?;
250 }
251 Ok(())
252 }
253}
254
255impl cmp::PartialEq for PublicKey {
256 fn eq(&self, other: &Self) -> bool {
257 self.to_bytes().eq(&other.to_bytes())
258 }
259}
260
261impl hash::Hash for PublicKey {
262 fn hash<H: hash::Hasher>(&self, state: &mut H) {
263 self.to_bytes().hash(state);
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270
271 #[test]
272 #[cfg(feature = "rand")]
273 fn sign_verify() {
274 let pair = Keypair::generate();
275 let pk = pair.public();
276
277 let msg = "hello world".as_bytes();
278 let sig = pair.sign(msg);
279 assert!(pk.verify(msg, &sig));
280
281 let mut invalid_sig = sig.clone();
282 invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
283 assert!(!pk.verify(msg, &invalid_sig));
284
285 let invalid_msg = "h3ll0 w0rld".as_bytes();
286 assert!(!pk.verify(invalid_msg, &sig));
287 }
288}