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 super::error::DecodingError;
24use asn1_der::typed::{DerDecodable, Sequence};
25use core::cmp;
26use core::fmt;
27use core::hash;
28use libsecp256k1::{Message, Signature};
29use sha2::{Digest as ShaDigestTrait, Sha256};
30use zeroize::Zeroize;
31
32/// A Secp256k1 keypair.
33#[derive(Clone)]
34pub struct Keypair {
35    secret: SecretKey,
36    public: PublicKey,
37}
38
39impl Keypair {
40    /// Generate a new sec256k1 `Keypair`.
41    #[cfg(feature = "rand")]
42    pub fn generate() -> Keypair {
43        Keypair::from(SecretKey::generate())
44    }
45
46    /// Get the public key of this keypair.
47    pub fn public(&self) -> &PublicKey {
48        &self.public
49    }
50
51    /// Get the secret key of this keypair.
52    pub fn secret(&self) -> &SecretKey {
53        &self.secret
54    }
55}
56
57impl fmt::Debug for Keypair {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        f.debug_struct("Keypair")
60            .field("public", &self.public)
61            .finish()
62    }
63}
64
65/// Promote a Secp256k1 secret key into a keypair.
66impl From<SecretKey> for Keypair {
67    fn from(secret: SecretKey) -> Keypair {
68        let public = PublicKey(libsecp256k1::PublicKey::from_secret_key(&secret.0));
69        Keypair { secret, public }
70    }
71}
72
73/// Demote a Secp256k1 keypair into a secret key.
74impl From<Keypair> for SecretKey {
75    fn from(kp: Keypair) -> SecretKey {
76        kp.secret
77    }
78}
79
80/// A Secp256k1 secret key.
81#[derive(Clone)]
82pub struct SecretKey(libsecp256k1::SecretKey);
83
84impl fmt::Debug for SecretKey {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        write!(f, "SecretKey")
87    }
88}
89
90impl SecretKey {
91    /// Generate a new random Secp256k1 secret key.
92    #[cfg(feature = "rand")]
93    pub fn generate() -> SecretKey {
94        SecretKey(libsecp256k1::SecretKey::random(&mut rand::thread_rng()))
95    }
96
97    /// Create a secret key from a byte slice, zeroing the slice on success.
98    /// If the bytes do not constitute a valid Secp256k1 secret key, an
99    /// error is returned.
100    ///
101    /// Note that the expected binary format is the same as `libsecp256k1`'s.
102    pub fn try_from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
103        let sk_bytes = sk.as_mut();
104        let secret = libsecp256k1::SecretKey::parse_slice(&*sk_bytes)
105            .map_err(|e| DecodingError::failed_to_parse("parse secp256k1 secret key", e))?;
106        sk_bytes.zeroize();
107        Ok(SecretKey(secret))
108    }
109
110    /// Decode a DER-encoded Secp256k1 secret key in an ECPrivateKey
111    /// structure as defined in [RFC5915], zeroing the input slice on success.
112    ///
113    /// [RFC5915]: https://tools.ietf.org/html/rfc5915
114    pub fn from_der(mut der: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
115        // TODO: Stricter parsing.
116        let der_obj = der.as_mut();
117
118        let mut sk_bytes = Sequence::decode(der_obj)
119            .and_then(|seq| seq.get(1))
120            .and_then(Vec::load)
121            .map_err(|e| DecodingError::failed_to_parse("secp256k1 SecretKey bytes", e))?;
122
123        let sk = SecretKey::try_from_bytes(&mut sk_bytes)?;
124        sk_bytes.zeroize();
125        der_obj.zeroize();
126        Ok(sk)
127    }
128
129    /// Sign a message with this secret key, producing a DER-encoded
130    /// ECDSA signature, as defined in [RFC3278].
131    ///
132    /// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
133    pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
134        let generic_array = Sha256::digest(msg);
135
136        // FIXME: Once `generic-array` hits 1.0, we should be able to just use `Into` here.
137        let mut array = [0u8; 32];
138        array.copy_from_slice(generic_array.as_slice());
139
140        let message = Message::parse(&array);
141
142        libsecp256k1::sign(&message, &self.0)
143            .0
144            .serialize_der()
145            .as_ref()
146            .into()
147    }
148
149    /// Returns the raw bytes of the secret key.
150    pub fn to_bytes(&self) -> [u8; 32] {
151        self.0.serialize()
152    }
153}
154
155/// A Secp256k1 public key.
156#[derive(Eq, Clone)]
157pub struct PublicKey(libsecp256k1::PublicKey);
158
159impl fmt::Debug for PublicKey {
160    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161        f.write_str("PublicKey(compressed): ")?;
162        for byte in &self.to_bytes() {
163            write!(f, "{byte:x}")?;
164        }
165        Ok(())
166    }
167}
168
169impl cmp::PartialEq for PublicKey {
170    fn eq(&self, other: &Self) -> bool {
171        self.to_bytes().eq(&other.to_bytes())
172    }
173}
174
175impl hash::Hash for PublicKey {
176    fn hash<H: hash::Hasher>(&self, state: &mut H) {
177        self.to_bytes().hash(state);
178    }
179}
180
181impl cmp::PartialOrd for PublicKey {
182    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
183        Some(self.cmp(other))
184    }
185}
186
187impl cmp::Ord for PublicKey {
188    fn cmp(&self, other: &Self) -> cmp::Ordering {
189        self.to_bytes().cmp(&other.to_bytes())
190    }
191}
192
193impl PublicKey {
194    /// Verify the Secp256k1 signature on a message using the public key.
195    pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
196        self.verify_hash(Sha256::digest(msg).as_ref(), sig)
197    }
198
199    /// Verify the Secp256k1 DER-encoded signature on a raw 256-bit message using the public key.
200    pub fn verify_hash(&self, msg: &[u8], sig: &[u8]) -> bool {
201        Message::parse_slice(msg)
202            .and_then(|m| Signature::parse_der(sig).map(|s| libsecp256k1::verify(&m, &s, &self.0)))
203            .unwrap_or(false)
204    }
205
206    /// Convert the public key to a byte buffer in compressed form, i.e. with one coordinate
207    /// represented by a single bit.
208    pub fn to_bytes(&self) -> [u8; 33] {
209        self.0.serialize_compressed()
210    }
211
212    /// Convert the public key to a byte buffer in uncompressed form.
213    pub fn to_bytes_uncompressed(&self) -> [u8; 65] {
214        self.0.serialize()
215    }
216
217    /// Decode a public key from a byte slice in the format produced
218    /// by `encode`.
219    pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
220        libsecp256k1::PublicKey::parse_slice(k, Some(libsecp256k1::PublicKeyFormat::Compressed))
221            .map_err(|e| DecodingError::failed_to_parse("secp256k1 public key", e))
222            .map(PublicKey)
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229
230    #[test]
231    #[cfg(feature = "rand")]
232    fn secp256k1_secret_from_bytes() {
233        let sk1 = SecretKey::generate();
234        let mut sk_bytes = [0; 32];
235        sk_bytes.copy_from_slice(&sk1.0.serialize()[..]);
236        let sk2 = SecretKey::try_from_bytes(&mut sk_bytes).unwrap();
237        assert_eq!(sk1.0.serialize(), sk2.0.serialize());
238        assert_eq!(sk_bytes, [0; 32]);
239    }
240}