laron_crypto/
private_key.rs

1// This file is part of the laron-crypto
2//
3// Copyright 2023 Ade M Ramdani
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18use constant_time_eq::constant_time_eq;
19use k256::ecdsa::VerifyingKey;
20use k256::NonZeroScalar;
21use rand::RngCore;
22
23use crate::{
24    error::{Error, Result},
25    PublicKey,
26};
27
28/// Byte size of the PrivateKey
29const SIZE: usize = 32;
30
31/// Private Key
32#[derive(Debug, Clone, Copy)]
33pub struct PrivateKey {
34    bytes: [u8; SIZE],
35}
36
37impl PartialEq for PrivateKey {
38    fn eq(&self, other: &Self) -> bool {
39        constant_time_eq(&self.bytes, &other.bytes)
40    }
41}
42
43impl Eq for PrivateKey {}
44
45impl PrivateKey {
46    /// Create a new PrivateKey
47    pub fn new() -> Self {
48        let mut rng = rand::thread_rng();
49        let mut bytes = [0u8; SIZE];
50        rng.fill_bytes(&mut bytes);
51        Self { bytes }
52    }
53
54    /// Create a new PrivateKey from bytes
55    pub fn from_bytes(bytes: [u8; SIZE]) -> Self {
56        Self { bytes }
57    }
58
59    /// Create a new PrivateKey from slice
60    pub fn from_slice(slice: &[u8]) -> Result<Self> {
61        if slice.len() != SIZE {
62            Err(Error::LengthError(
63                "PrivateKey size must be 32 bytes".to_string(),
64            ))
65        } else {
66            let mut new_bytes = [0u8; SIZE];
67            new_bytes.copy_from_slice(slice);
68            Ok(Self::from_bytes(new_bytes))
69        }
70    }
71
72    /// Create a new PrivateKey from hex string
73    pub fn from_hex(hex: &str) -> Result<Self> {
74        if hex.len() != SIZE * 2 {
75            Err(Error::LengthError(
76                "PrivateKey hex must be 64 characters".to_string(),
77            ))
78        } else {
79            let bytes = hex::decode(hex)?;
80            Self::from_slice(&bytes)
81        }
82    }
83
84    /// Get the PrivateKey as bytes
85    pub fn as_bytes(&self) -> [u8; SIZE] {
86        self.bytes
87    }
88
89    /// Get the PrivateKey as slice
90    pub fn as_slice(&self) -> &[u8] {
91        &self.bytes
92    }
93
94    /// Get the PrivateKey as hex string
95    pub fn as_hex(&self) -> String {
96        hex::encode(self.bytes)
97    }
98
99    /// Generate public key.
100    pub fn public_key(&self) -> PublicKey {
101        let sk = k256::SecretKey::from_slice(&self.bytes).unwrap();
102        let pk = sk.public_key();
103        let vk: VerifyingKey = pk.into();
104        let bytes = vk.to_encoded_point(false);
105        PublicKey::from_slice(bytes.as_bytes()).unwrap()
106    }
107
108    /// Derive child key from parent key.
109    pub fn derive_child(&self, other: [u8; 32]) -> Result<Self> {
110        let current = k256::SecretKey::from_slice(&self.bytes).unwrap();
111        let child_scalar = Option::<NonZeroScalar>::from(NonZeroScalar::from_repr(other.into()))
112            .ok_or(Error::PrivateKeyError)?;
113        let derived_scalar = current.to_nonzero_scalar().as_ref() + child_scalar.as_ref();
114        let derived: k256::SecretKey =
115            Option::<NonZeroScalar>::from(NonZeroScalar::new(derived_scalar))
116                .map(Into::into)
117                .ok_or(Error::PrivateKeyError)?;
118        let bytes = derived.to_bytes();
119        Self::from_slice(bytes.as_slice())
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126
127    #[test]
128    fn test_private_key() {
129        let key = PrivateKey::new();
130        let bytes = key.as_bytes();
131        assert_eq!(bytes.len(), 32);
132        let slice = key.as_slice();
133        assert_eq!(slice.len(), 32);
134        let hex = key.as_hex();
135        assert_eq!(hex.len(), 64);
136        let key2 = PrivateKey::from_hex(&hex).unwrap();
137        assert_eq!(key, key2);
138    }
139}