sym_crypto/
keypair.rs

1// Copyright 2021 BlockPuppets developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! A Rust implementation of Symbol ed25519 keypair generation, signing, and verification.
10//!
11//! This is the reference documentation for the proptest API.
12//!
13//! For documentation on how to get started with Symbol keypair and general usage
14//! advice, please refer to the [Key pair](https://docs.symbolplatform.com/concepts/cryptography.html#keypair).
15//!
16use ::std::convert::TryInto;
17use ::std::fmt;
18
19use anyhow::{ensure, Result};
20use rand::thread_rng;
21#[cfg(feature = "serde")]
22use serde::{Serialize, Serializer};
23#[cfg(feature = "serde")]
24use serde_bytes::Bytes as SerdeBytes;
25
26use core::ed25519::{self, Verifier};
27
28use super::CryptoSym;
29use crate::core::{
30    hex_to_vec, is_hex, KeyPairSchema, PrivateKey, PublicKey, Signature, KEY_STR_SIZE,
31};
32
33/// It represents an Symbol asymmetric private/public encryption key.
34///
35#[derive(Debug, Clone, Copy, PartialEq, Hash)]
36pub struct Keypair {
37    /// The private half of this keypair.
38    pub private_key: PrivateKey,
39    /// The public half of this keypair.
40    pub public_key: PublicKey,
41}
42
43impl KeyPairSchema for Keypair {
44    type Crypto = CryptoSym;
45
46    /// Create a new Symbol `Keypair` with cryptographically random content.
47    ///
48    fn random() -> Self {
49        let mut csprng = thread_rng();
50        let sk = ed25519::SecretKey::generate(&mut csprng);
51        let pk: ed25519::PublicKey = (&sk).into();
52
53        Self {
54            private_key: PrivateKey::from(sk.to_bytes()),
55            public_key: PublicKey::from(pk.to_bytes()),
56        }
57    }
58
59    /// Construct a Symbol `Keypair` from the bytes of a `PublicKey` and `PrivateKey`.
60    ///
61    fn from_bytes(bytes: &[u8]) -> Result<Self> {
62        let kp = ed25519::Keypair::from_bytes(bytes)?;
63        Ok(Keypair::from(PrivateKey::from(kp.secret.as_bytes())))
64    }
65
66    /// Construct a Symbol `Keypair` from a hex encoded private key string.
67    ///
68    /// # Inputs
69    ///
70    /// * `hex`: an `S` representing the hex private key (String or &str).
71    ///
72    /// # Returns
73    ///
74    /// A `Result` whose okay value is an Symbol `Keypair` or whose error value
75    /// is an `failure::Error` describing the error that occurred.
76    fn from_hex_private_key<S: AsRef<str>>(hex: S) -> Result<Self> {
77        let hex = hex.as_ref();
78        ensure!(is_hex(hex), "private_key it's not hex.");
79
80        ensure!(
81            KEY_STR_SIZE == hex.len(),
82            format!("private key has unexpected size {}", hex.len())
83        );
84
85        let sk = ed25519::SecretKey::from_bytes(&hex_to_vec(hex))?;
86
87        let pk: ed25519::PublicKey = (&sk).into();
88
89        Ok(Self {
90            private_key: PrivateKey::from(sk.to_bytes()),
91            public_key: PublicKey::from(pk.to_bytes()),
92        })
93    }
94
95    /// Construct a Symbol `Keypair` `PrivateKey` type.
96    ///
97    /// # Inputs
98    ///
99    /// * `private_key`: representing the `PrivateKey` type.
100    ///
101    /// # Returns
102    ///
103    /// A `Keypair`
104    fn from_private_key(pk: PrivateKey) -> Self {
105        let sk = ed25519::SecretKey::from_bytes(pk.as_bytes()).unwrap();
106
107        let pk: ed25519::PublicKey = (&sk).into();
108
109        Self {
110            private_key: PrivateKey::from(sk.to_bytes()),
111            public_key: PublicKey::from(pk.to_bytes()),
112        }
113    }
114
115    fn private_key(&self) -> PrivateKey {
116        self.private_key
117    }
118
119    fn public_key(&self) -> PublicKey {
120        self.public_key
121    }
122
123    /// Signs a data bytes with a Symbol `Keypair`.
124    ///
125    /// # Inputs
126    ///
127    /// * `data`: an `&[u8]` representing the data to sign.
128    ///
129    /// # Returns
130    ///
131    /// A `Signature` the signature hash.
132    fn sign(&self, data: &[u8]) -> Signature {
133        let kp = ed25519::Keypair::from_bytes(&self.to_bytes()).unwrap();
134
135        let expanded_sk: ed25519::ExpandedSecretKey = (&kp.secret).into();
136        (expanded_sk.sign(data, &kp.public).to_bytes()).into()
137    }
138
139    /// Verify a `Signature` on a data with this Symbol Keypair public key.
140    ///
141    /// # Inputs
142    ///
143    /// * `data`: an `&[u8]` the data to verify.
144    ///
145    /// * `signature`: an `Signature` the signature hash.
146    ///
147    /// # Returns
148    ///
149    /// Returns `Ok` if the `Signature` was a valid signature created by this Symbol `Keypair`
150    ///
151    fn verify(&self, data: &[u8], signature: Signature) -> Result<()> {
152        let pk = ed25519::PublicKey::from_bytes(self.public_key.as_bytes())?;
153        let signature: ed25519::Signature = (signature.as_bytes()).try_into()?;
154        Ok(pk.verify(data, &signature)?)
155    }
156
157    fn from_null_private_key(pk: PublicKey) -> Self {
158        Self {
159            private_key: PrivateKey::zero(),
160            public_key: pk,
161        }
162    }
163}
164
165impl<'a> From<&'a PrivateKey> for Keypair {
166    fn from(sk: &'a PrivateKey) -> Self {
167        Self::from_hex_private_key(format!("{:x}", sk)).unwrap()
168    }
169}
170
171impl From<PrivateKey> for Keypair {
172    fn from(sk: PrivateKey) -> Self {
173        Self::from_hex_private_key(format!("{:x}", sk)).unwrap()
174    }
175}
176
177impl fmt::Display for Keypair {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        write!(f, " public_key: {:x}", self.public_key)
180    }
181}
182
183#[cfg(feature = "serde")]
184impl Serialize for Keypair {
185    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
186    where
187        S: Serializer,
188    {
189        let bytes = &self.to_bytes()[..];
190        SerdeBytes::new(bytes).serialize(serializer)
191    }
192}