libp2p_identity/
secp256k1.rs

1// Copyright 2019 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! Secp256k1 keys.
22
23use 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/// A Secp256k1 keypair.
36#[derive(Clone)]
37pub struct Keypair {
38    secret: SecretKey,
39    public: PublicKey,
40}
41
42impl Keypair {
43    /// Generate a new sec256k1 `Keypair`.
44    #[cfg(feature = "rand")]
45    pub fn generate() -> Keypair {
46        Keypair::from(SecretKey::generate())
47    }
48
49    /// Get the public key of this keypair.
50    pub fn public(&self) -> &PublicKey {
51        &self.public
52    }
53
54    /// Get the secret key of this keypair.
55    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
68/// Promote a Secp256k1 secret key into a keypair.
69impl 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
76/// Demote a Secp256k1 keypair into a secret key.
77impl From<Keypair> for SecretKey {
78    fn from(kp: Keypair) -> SecretKey {
79        kp.secret
80    }
81}
82
83/// A Secp256k1 secret key.
84#[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    /// Generate a new random Secp256k1 secret key.
95    #[cfg(feature = "rand")]
96    pub fn generate() -> SecretKey {
97        SecretKey(k256::ecdsa::SigningKey::random(&mut rand::thread_rng()))
98    }
99
100    /// Create a secret key from a byte slice, zeroing the slice on success.
101    /// If the bytes do not constitute a valid Secp256k1 secret key, an
102    /// error is returned.
103    ///
104    /// Note that the expected binary format is the same as `libsecp256k1`'s.
105    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    /// Decode a DER-encoded Secp256k1 secret key in an ECPrivateKey
114    /// structure as defined in [RFC5915], zeroing the input slice on success.
115    ///
116    /// [RFC5915]: https://tools.ietf.org/html/rfc5915
117    pub fn from_der(mut der: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
118        // TODO: Stricter parsing.
119        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    /// Sign a message with this secret key, producing a DER-encoded
133    /// ECDSA signature, as defined in [RFC3278].
134    ///
135    /// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
136    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    /// Returns the raw bytes of the secret key.
146    pub fn to_bytes(&self) -> [u8; 32] {
147        self.0.to_bytes().into()
148    }
149}
150
151/// A Secp256k1 public key.
152#[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    /// Verify the Secp256k1 signature on a message using the public key.
191    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    /// Verify the Secp256k1 DER-encoded signature on a raw 256-bit message using the public key.  
197    /// Will return false if the hash is not 32 bytes long, or the signature cannot be parsed.
198    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    /// Convert the public key to a byte buffer in compressed form, i.e. with one coordinate
210    /// represented by a single bit.
211    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    /// Convert the public key to a byte buffer in uncompressed form.
220    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    /// Decode a public key from a byte slice in the format produced
229    /// by `encode`.
230    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}