libp2p_identity/
secp256k1.rs1use core::{cmp, fmt, hash};
24
25use asn1_der::typed::{DerDecodable, Sequence};
26use k256::{
27 ecdsa::Signature,
28 sha2::{Digest as ShaDigestTrait, Sha256},
29 ProjectivePoint,
30};
31use zeroize::Zeroize;
32
33use super::error::DecodingError;
34
35#[derive(Clone)]
37pub struct Keypair {
38 secret: SecretKey,
39 public: PublicKey,
40}
41
42impl Keypair {
43 #[cfg(feature = "rand")]
45 pub fn generate() -> Keypair {
46 Keypair::from(SecretKey::generate())
47 }
48
49 pub fn public(&self) -> &PublicKey {
51 &self.public
52 }
53
54 pub fn secret(&self) -> &SecretKey {
56 &self.secret
57 }
58}
59
60impl fmt::Debug for Keypair {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f.debug_struct("Keypair")
63 .field("public", &self.public)
64 .finish()
65 }
66}
67
68impl From<SecretKey> for Keypair {
70 fn from(secret: SecretKey) -> Keypair {
71 let public = PublicKey(*secret.0.verifying_key());
72 Keypair { secret, public }
73 }
74}
75
76impl From<Keypair> for SecretKey {
78 fn from(kp: Keypair) -> SecretKey {
79 kp.secret
80 }
81}
82
83#[derive(Clone)]
85pub struct SecretKey(k256::ecdsa::SigningKey);
86
87impl fmt::Debug for SecretKey {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 write!(f, "SecretKey")
90 }
91}
92
93impl SecretKey {
94 #[cfg(feature = "rand")]
96 pub fn generate() -> SecretKey {
97 SecretKey(k256::ecdsa::SigningKey::random(&mut rand::thread_rng()))
98 }
99
100 pub fn try_from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
106 let sk_bytes = sk.as_mut();
107 let secret = k256::ecdsa::SigningKey::from_slice(sk_bytes)
108 .map_err(|e| DecodingError::failed_to_parse("parse secp256k1 secret key", e))?;
109 sk_bytes.zeroize();
110 Ok(SecretKey(secret))
111 }
112
113 pub fn from_der(mut der: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
118 let der_obj = der.as_mut();
120
121 let mut sk_bytes = Sequence::decode(der_obj)
122 .and_then(|seq| seq.get(1))
123 .and_then(Vec::load)
124 .map_err(|e| DecodingError::failed_to_parse("secp256k1 SecretKey bytes", e))?;
125
126 let sk = SecretKey::try_from_bytes(&mut sk_bytes)?;
127 sk_bytes.zeroize();
128 der_obj.zeroize();
129 Ok(sk)
130 }
131
132 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
137 use k256::ecdsa::signature::Signer;
138
139 Signer::<k256::ecdsa::Signature>::sign(&self.0, msg)
140 .to_der()
141 .to_bytes()
142 .into_vec()
143 }
144
145 pub fn to_bytes(&self) -> [u8; 32] {
147 self.0.to_bytes().into()
148 }
149}
150
151#[derive(Eq, Clone)]
153pub struct PublicKey(k256::ecdsa::VerifyingKey);
154
155impl fmt::Debug for PublicKey {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 f.write_str("PublicKey(compressed): ")?;
158 for byte in &self.to_bytes() {
159 write!(f, "{byte:x}")?;
160 }
161 Ok(())
162 }
163}
164
165impl cmp::PartialEq for PublicKey {
166 fn eq(&self, other: &Self) -> bool {
167 self.to_bytes().eq(&other.to_bytes())
168 }
169}
170
171impl hash::Hash for PublicKey {
172 fn hash<H: hash::Hasher>(&self, state: &mut H) {
173 self.to_bytes().hash(state);
174 }
175}
176
177impl cmp::PartialOrd for PublicKey {
178 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
179 Some(self.cmp(other))
180 }
181}
182
183impl cmp::Ord for PublicKey {
184 fn cmp(&self, other: &Self) -> cmp::Ordering {
185 self.to_bytes().cmp(&other.to_bytes())
186 }
187}
188
189impl PublicKey {
190 pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
192 let digest = Sha256::new_with_prefix(msg);
193 self.verify_hash(digest.finalize().as_slice(), sig)
194 }
195
196 pub fn verify_hash(&self, msg: &[u8], sig: &[u8]) -> bool {
199 Signature::from_der(sig).is_ok_and(|s| {
200 k256::ecdsa::hazmat::verify_prehashed(
201 &ProjectivePoint::from(self.0.as_affine()),
202 msg.into(),
203 &s,
204 )
205 .is_ok()
206 })
207 }
208
209 pub fn to_bytes(&self) -> [u8; 33] {
212 let encoded_point = self.0.to_encoded_point(true);
213 debug_assert!(encoded_point.as_bytes().len() == 33);
214 let mut array: [u8; 33] = [0u8; 33];
215 array.copy_from_slice(encoded_point.as_bytes());
216 array
217 }
218
219 pub fn to_bytes_uncompressed(&self) -> [u8; 65] {
221 let encoded_point = self.0.to_encoded_point(false);
222 debug_assert!(encoded_point.as_bytes().len() == 65);
223 let mut array: [u8; 65] = [0u8; 65];
224 array.copy_from_slice(encoded_point.as_bytes());
225 array
226 }
227
228 pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
231 k256::ecdsa::VerifyingKey::from_sec1_bytes(k)
232 .map_err(|e| DecodingError::failed_to_parse("secp256k1 public key", e))
233 .map(PublicKey)
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240
241 #[test]
242 #[cfg(feature = "rand")]
243 fn secp256k1_secret_from_bytes() {
244 let sk1 = SecretKey::generate();
245 let mut sk_bytes = [0; 32];
246 sk_bytes.copy_from_slice(&sk1.to_bytes()[..]);
247 let sk2 = SecretKey::try_from_bytes(&mut sk_bytes).unwrap();
248 assert_eq!(sk1.to_bytes(), sk2.to_bytes());
249 assert_eq!(sk_bytes, [0; 32]);
250 }
251}