substrate_stellar_sdk/
public_key.rs

1use core::convert::TryInto;
2
3use sp_std::{vec, vec::Vec};
4
5use crate::{
6    lib::{String, ToString},
7    utils::key_encoding::{
8        decode_stellar_key, encode_stellar_key, ED25519_PUBLIC_KEY_BYTE_LENGTH, ED25519_PUBLIC_KEY_VERSION_BYTE,
9    },
10    PublicKey, StellarSdkError, XdrCodec,
11};
12
13use crate::utils::std::StellarTypeToString;
14
15use sodalite::{sign_attached_open, Sign as Signature, SIGN_LEN};
16
17pub trait IntoPublicKey {
18    fn into_public_key(self) -> Result<PublicKey, StellarSdkError>;
19}
20
21impl IntoPublicKey for PublicKey {
22    fn into_public_key(self) -> Result<PublicKey, StellarSdkError> {
23        Ok(self)
24    }
25}
26
27impl<T: AsRef<[u8]>> IntoPublicKey for T {
28    fn into_public_key(self) -> Result<PublicKey, StellarSdkError> {
29        PublicKey::from_encoding(self)
30    }
31}
32
33impl<E: From<sp_std::str::Utf8Error>> StellarTypeToString<Self, E> for PublicKey {
34    fn as_encoded_string(&self) -> Result<String, E> {
35        let x = self.to_encoding();
36        let str = sp_std::str::from_utf8(&x).map_err(E::from)?;
37        Ok(str.to_string())
38    }
39}
40
41impl<E: From<sp_std::str::Utf8Error>> StellarTypeToString<PublicKey, E> for &str {
42    fn as_encoded_string(&self) -> Result<String, E> {
43        Ok(self.to_string())
44    }
45}
46
47impl<E: From<sp_std::str::Utf8Error>> StellarTypeToString<PublicKey, E> for Vec<u8> {
48    fn as_encoded_string(&self) -> Result<String, E> {
49        let str = sp_std::str::from_utf8(self).map_err(E::from)?;
50        Ok(str.to_string())
51    }
52}
53
54/// The public key of an Ed25519 signing key pair
55///
56/// This type is also used for Stellar account ids.
57/// ```
58/// let public = "GBIVKYSF6RP4U57KPZ524X47NGTQYYPZAZ4UX5ZFYAYBJWRFXHKHDQVL";
59/// let public_key = substrate_stellar_sdk::types::PublicKey::from_encoding(public);
60/// assert!(public_key.is_ok());
61/// let public_key = public_key.unwrap();
62/// assert_eq!(&public_key.to_encoding().as_slice(), &public.as_bytes());
63/// ```
64impl PublicKey {
65    pub fn from_binary(binary: [u8; ED25519_PUBLIC_KEY_BYTE_LENGTH]) -> Self {
66        PublicKey::PublicKeyTypeEd25519(binary)
67    }
68
69    /// Return the raw binary key as a reference
70    pub fn as_binary(&self) -> &[u8; ED25519_PUBLIC_KEY_BYTE_LENGTH] {
71        match self {
72            PublicKey::PublicKeyTypeEd25519(key) => key,
73        }
74    }
75
76    /// Turn into the raw binary key
77    pub fn into_binary(self) -> [u8; ED25519_PUBLIC_KEY_BYTE_LENGTH] {
78        *self.as_binary()
79    }
80
81    pub fn from_encoding<T: AsRef<[u8]>>(encoded_key: T) -> Result<Self, StellarSdkError> {
82        let decoded_key = decode_stellar_key(encoded_key, ED25519_PUBLIC_KEY_VERSION_BYTE)?;
83        Ok(Self::from_binary(decoded_key))
84    }
85
86    /// Return the key encoding as an ASCII string (given as `Vec<u8>`)
87    pub fn to_encoding(&self) -> Vec<u8> {
88        let key = self.as_binary();
89        encode_stellar_key(key, ED25519_PUBLIC_KEY_VERSION_BYTE)
90    }
91
92    pub fn get_signature_hint(&self) -> [u8; 4] {
93        let account_id_xdr = Self::PublicKeyTypeEd25519(self.as_binary().clone()).to_xdr();
94
95        account_id_xdr[account_id_xdr.len() - 4..].try_into().unwrap()
96    }
97
98    /// Verify the signature of a message.
99    ///
100    /// Given the raw binary `message`, check whether the raw binary `signature` is valid.
101    pub fn verify_signature<T: AsRef<[u8]>>(&self, message: T, signature: &Signature) -> bool {
102        let message = message.as_ref();
103        let mut signed_message: Vec<u8> = Vec::with_capacity(message.len() + SIGN_LEN);
104
105        signed_message.extend_from_slice(signature);
106        signed_message.extend_from_slice(message);
107
108        sign_attached_open(&mut vec![0; message.len() + SIGN_LEN], &signed_message, self.as_binary()).is_ok()
109    }
110}