fluence_identity/
public_key.rs

1/*
2 * Copyright 2021 Fluence Labs Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16use crate::ed25519;
17#[cfg(not(target_arch = "wasm32"))]
18use crate::rsa;
19use crate::secp256k1;
20use crate::error::{DecodingError, SigningError};
21use crate::signature::Signature;
22
23use serde::{Deserialize, Serialize};
24use crate::key_pair::KeyFormat;
25use std::convert::TryFrom;
26
27/// The public key of a node's identity keypair.
28#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
29pub enum PublicKey {
30    /// A public Ed25519 key.
31    Ed25519(ed25519::PublicKey),
32    #[cfg(not(target_arch = "wasm32"))]
33    /// A public RSA key.
34    Rsa(rsa::PublicKey),
35    /// A public Secp256k1 key.
36    Secp256k1(secp256k1::PublicKey),
37}
38
39impl PublicKey {
40    /// Verify a signature for a message using this public key, i.e. check
41    /// that the signature has been produced by the corresponding
42    /// private key (authenticity), and that the message has not been
43    /// tampered with (integrity).
44    pub fn verify(&self, msg: &[u8], sig: &Signature) -> Result<(), SigningError> {
45        use PublicKey::*;
46        match self {
47            Ed25519(pk) => pk.verify(msg, sig.to_vec()),
48            #[cfg(not(target_arch = "wasm32"))]
49            Rsa(pk) => pk.verify(msg, sig.to_vec()),
50            Secp256k1(pk) => pk.verify(msg, sig.to_vec())
51        }
52    }
53
54    pub fn encode(&self) -> Vec<u8> {
55        use PublicKey::*;
56        let mut result: Vec<u8> = vec![self.get_prefix()];
57
58        match self {
59            Ed25519(pk) => result.extend(pk.encode().to_vec()),
60            #[cfg(not(target_arch = "wasm32"))]
61            Rsa(pk) => result.extend(pk.to_pkcs1()),
62            Secp256k1(pk) => result.extend(pk.encode().to_vec()),
63        };
64
65        result
66    }
67
68    pub fn decode(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
69        match KeyFormat::try_from(bytes[0])? {
70            KeyFormat::Ed25519 => Ok(PublicKey::Ed25519(ed25519::PublicKey::decode(&bytes[1..])?)),
71            #[cfg(not(target_arch = "wasm32"))]
72            KeyFormat::Rsa => Ok(PublicKey::Rsa(rsa::PublicKey::from_pkcs1(bytes[1..].to_owned())?)),
73            KeyFormat::Secp256k1 => Ok(PublicKey::Secp256k1(secp256k1::PublicKey::decode(&bytes[1..])?)),
74        }
75    }
76
77    fn get_prefix(&self) -> u8 {
78        use PublicKey::*;
79        match self {
80            Ed25519(_) => KeyFormat::Ed25519.into(),
81            #[cfg(not(target_arch = "wasm32"))]
82            Rsa(_) => KeyFormat::Rsa.into(),
83            Secp256k1(_) => KeyFormat::Secp256k1.into()
84        }
85    }
86
87    pub fn from_base58(str: &str) -> Result<PublicKey, DecodingError> {
88        let bytes = bs58::decode(str).into_vec().map_err(DecodingError::Base58DecodeError)?;
89        Self::decode(&bytes)
90    }
91
92    pub fn to_vec(&self) -> Vec<u8> {
93        use PublicKey::*;
94
95        match self {
96            Ed25519(pk) => pk.encode().to_vec(),
97            #[cfg(not(target_arch = "wasm32"))]
98            Rsa(pk) => pk.to_pkcs1().to_vec(),
99            Secp256k1(pk) => pk.encode().to_vec(),
100        }
101    }
102}
103
104impl From<libp2p_core::identity::PublicKey> for PublicKey {
105    fn from(key: libp2p_core::identity::PublicKey) -> Self {
106        use libp2p_core::identity::PublicKey::*;
107
108        match key {
109            Ed25519(key) => PublicKey::Ed25519(ed25519::PublicKey::decode(&key.encode()[..]).unwrap()),
110            #[cfg(not(target_arch = "wasm32"))]
111            Rsa(key) => PublicKey::Rsa(rsa::PublicKey::from_pkcs1(key.encode_pkcs1()).unwrap()),
112            Secp256k1(key) => PublicKey::Secp256k1(secp256k1::PublicKey::decode(&key.encode()[..]).unwrap()),
113        }
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use super::*;
120    use crate::KeyPair;
121
122    #[test]
123    fn public_key_encode_decode_ed25519() {
124        let kp = KeyPair::generate_ed25519();
125        let pk = kp.public();
126        let encoded_pk = pk.encode();
127        assert_eq!(pk, PublicKey::decode(&encoded_pk).unwrap());
128    }
129
130    #[test]
131    fn public_key_encode_decode_secp256k1() {
132        let kp = KeyPair::generate_secp256k1();
133        let pk = kp.public();
134        let encoded_pk = pk.encode();
135        assert_eq!(pk, PublicKey::decode(&encoded_pk).unwrap());
136    }
137}