Skip to main content

laron_crypto/
k256.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 k256::ecdsa;
19use k256::ecdsa::signature::DigestVerifier;
20use k256::ecdsa::{RecoveryId, SigningKey, VerifyingKey};
21use sha3::{Digest, Keccak256};
22
23use crate::error::{Error, Result};
24use crate::{PrivateKey, PublicKey};
25
26/// Wrapper for K256 signature.
27#[derive(Debug, Clone, Copy, Eq, PartialEq)]
28pub struct Signature {
29    sig: [u8; 64],
30    id: u8,
31}
32
33impl Signature {
34    /// Create a new signature.
35    pub fn new() -> Self {
36        Self {
37            sig: [0u8; 64],
38            id: 0,
39        }
40    }
41
42    /// Create a new signature from bytes.
43    pub fn from_bytes(bytes: [u8; 65]) -> Self {
44        let mut res = Self::new();
45        res.sig.copy_from_slice(&bytes[..64]);
46        res.id = bytes[64];
47        res
48    }
49
50    /// Create a new signature from slice.
51    pub fn from_slice(bytes: &[u8]) -> Result<Self> {
52        if bytes.len() != 64 {
53            return Err(Error::InvalidSignature);
54        }
55        let mut res = Self::new();
56        res.sig.copy_from_slice(bytes);
57        if bytes.len() == 65 {
58            res.id = bytes[64];
59        }
60        Ok(res)
61    }
62
63    /// Create a new signature from hex string.
64    pub fn from_hex(hex: &str) -> Result<Self> {
65        let bytes = hex::decode(hex)?;
66        Self::from_slice(&bytes)
67    }
68
69    /// Get the signature as bytes.
70    pub fn as_bytes(&self) -> [u8; 65] {
71        let mut res = [0u8; 65];
72        res[..64].copy_from_slice(&self.sig);
73        res[64] = self.id;
74        res
75    }
76
77    /// Get the signature as slice.
78    pub fn as_slice(&self) -> &[u8] {
79        let bytes = self.as_bytes();
80        Box::leak(Box::new(bytes))
81    }
82
83    /// Get the signature as hex string.
84    pub fn as_hex(&self) -> String {
85        let bytes = self.as_bytes();
86        hex::encode(bytes)
87    }
88}
89
90impl From<ecdsa::Signature> for Signature {
91    fn from(sig: ecdsa::Signature) -> Self {
92        let mut res = Self::new();
93        res.sig.copy_from_slice(sig.to_bytes().as_slice());
94        res
95    }
96}
97
98impl From<&Signature> for ecdsa::Signature {
99    fn from(value: &Signature) -> Self {
100        Self::from_slice(&value.sig).unwrap()
101    }
102}
103
104impl From<&Signature> for RecoveryId {
105    fn from(value: &Signature) -> Self {
106        Self::from_byte(value.id).unwrap()
107    }
108}
109
110/// K256Sign trait provides the interface for K256
111/// Signing.
112pub trait K256Sign {
113    /// Sign a message with the private key
114    fn sign(&self, msg: &str) -> Signature;
115}
116
117/// K256Verify trait provides the interface for K256
118/// Verification.
119pub trait K256Verify {
120    /// Verify a signature with the public key.
121    fn verify(&self, msg: &str, signature: &Signature) -> bool;
122}
123
124/// K256Recover trait provides the interface for K256
125/// Recovery.
126pub trait K256Recover {
127    /// Recover a public key from a signature.
128    fn recover(msg: &str, signature: &Signature) -> Result<PublicKey>;
129}
130
131impl From<&PrivateKey> for SigningKey {
132    fn from(value: &PrivateKey) -> Self {
133        Self::from_slice(value.as_slice()).unwrap()
134    }
135}
136
137impl From<SigningKey> for PrivateKey {
138    fn from(value: SigningKey) -> Self {
139        let bytes = value.to_bytes();
140        Self::from_slice(bytes.as_slice()).unwrap()
141    }
142}
143
144impl From<&PublicKey> for VerifyingKey {
145    fn from(value: &PublicKey) -> Self {
146        Self::from_sec1_bytes(value.as_slice()).unwrap()
147    }
148}
149
150impl From<VerifyingKey> for PublicKey {
151    fn from(value: VerifyingKey) -> Self {
152        let bytes = value.to_encoded_point(false);
153        Self::from_slice(bytes.as_bytes()).unwrap()
154    }
155}
156
157impl K256Sign for PrivateKey {
158    fn sign(&self, msg: &str) -> Signature {
159        let digest = Keccak256::new_with_prefix(msg.as_bytes());
160        let key: SigningKey = self.into();
161        let (sig, id) = key.sign_digest_recoverable(digest).unwrap();
162        let mut signature: Signature = sig.into();
163        signature.id = id.to_byte();
164        signature
165    }
166}
167
168impl K256Verify for PublicKey {
169    fn verify(&self, msg: &str, signature: &Signature) -> bool {
170        let digest = Keccak256::new_with_prefix(msg.as_bytes());
171        let key: VerifyingKey = self.into();
172        let sig: ecdsa::Signature = signature.into();
173        key.verify_digest(digest, &sig).is_ok()
174    }
175}
176
177impl K256Recover for PrivateKey {
178    fn recover(msg: &str, signature: &Signature) -> Result<PublicKey> {
179        let digest = Keccak256::new_with_prefix(msg.as_bytes());
180        let sig: ecdsa::Signature = signature.into();
181        let id: RecoveryId = signature.into();
182        let recovered = VerifyingKey::recover_from_digest(digest, &sig, id)
183            .map_err(|e| Error::RecoveryError(e.to_string()))?;
184        let recovered_bytes = recovered.to_encoded_point(false);
185        PublicKey::from_slice(recovered_bytes.as_bytes())
186    }
187}
188
189impl K256Recover for PublicKey {
190    fn recover(msg: &str, signature: &Signature) -> Result<PublicKey> {
191        PrivateKey::recover(msg, signature)
192    }
193}
194
195#[cfg(test)]
196mod tests {
197    use super::*;
198
199    #[test]
200    fn test_k256() {
201        let sk = PrivateKey::new();
202        let pk = sk.public_key();
203        let msg = "hello world";
204        let signature = sk.sign(msg);
205        assert!(pk.verify(msg, &signature));
206        let recovered = PublicKey::recover(msg, &signature).unwrap();
207        assert_eq!(pk, recovered);
208    }
209}