1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use crate::{Base58PublicKey, Ed25519PublicKeyArray, Ed25519SignatureArray};
use ed25519_dalek::{Keypair, PublicKey, Signature, Verifier};
use wasmium_errors::{WasmiumError, WasmiumResult};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WasmiumSignature<'ws> {
    message: &'ws [u8],
    signature: Signature,
    public_key: PublicKey,
}

impl<'ws> WasmiumSignature<'ws> {
    pub fn add_message(&mut self, message: &'ws [u8]) -> &mut WasmiumSignature<'ws> {
        self.message = message;

        self
    }

    pub fn add_signature(
        &mut self,
        signature_array: Ed25519SignatureArray,
    ) -> Result<&mut WasmiumSignature<'ws>, WasmiumOutcome> {
        match Utilities::array_to_ed25519_signature(signature_array) {
            Ok(signature) => {
                self.signature = signature;
                Ok(self)
            }
            Err(error_outcome) => return Err(error_outcome),
        }
    }

    pub fn add_public_key(
        &mut self,
        public_key_array: Ed25519PublicKeyArray,
    ) -> Result<&mut WasmiumSignature<'ws>, WasmiumOutcome> {
        match Utilities::array_to_ed25519_public_key(public_key_array) {
            Ok(public_key) => {
                self.public_key = public_key;
                Ok(self)
            }
            Err(error_outcome) => return Err(error_outcome),
        }
    }

    pub fn verify_signature(&self) -> WasmiumOutcome {
        match self.public_key.verify(&self.message, &self.signature) {
            Ok(_) => WasmiumOutcome::ValidSignature,
            Err(_) => WasmiumOutcome::InvalidSignature,
        }
    }
}

impl<'ws> Default for WasmiumSignature<'ws> {
    fn default() -> Self {
        WasmiumSignature {
            message: b"WASMIUM_KEEPER",
            signature: Signature::from_bytes(&[0_u8; 64]).unwrap(), //Never fails
            public_key: PublicKey::from_bytes(&[0_u8; 32]).unwrap(), //Never fails
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum WasmiumOutcome {
    ValidSignature,
    InvalidSignature,
    InvalidSignatureBytes,
    InvalidPublicKeyBytes,
    InvalidKeypairBytes,
}

#[derive(Debug)]
pub struct Utilities;

impl Utilities {
    pub fn base58_to_public_key_array(value: Base58PublicKey) -> WasmiumResult<[u8; 32]> {
        let decoded_value = match bs58::decode(&value).into_vec() {
            Ok(decoded) => decoded,
            Err(_) => return Err(WasmiumError::InvalidBase58ForPublickKey),
        };

        let converted_value: [u8; 32] = match decoded_value.try_into() {
            Ok(public) => public,
            Err(_) => return Err(WasmiumError::ErrorConvertingToU832),
        };

        Ok(converted_value)
    }

    pub fn array_to_ed25519_keypair(keypair_array: [u8; 64]) -> Result<Keypair, WasmiumOutcome> {
        match Keypair::from_bytes(&keypair_array) {
            Ok(keypair) => Ok(keypair),
            Err(_) => return Err(WasmiumOutcome::InvalidKeypairBytes),
        }
    }

    pub fn array_to_ed25519_public_key(
        public_key_array: [u8; 32],
    ) -> Result<PublicKey, WasmiumOutcome> {
        match PublicKey::from_bytes(&public_key_array) {
            Ok(public_key) => Ok(public_key),
            Err(_) => return Err(WasmiumOutcome::InvalidPublicKeyBytes),
        }
    }

    pub fn array_to_ed25519_signature(
        signature_array: [u8; 64],
    ) -> Result<Signature, WasmiumOutcome> {
        match Signature::from_bytes(&signature_array) {
            Ok(signature) => Ok(signature),
            Err(_) => Err(WasmiumOutcome::InvalidSignatureBytes),
        }
    }
}

#[cfg(test)]
mod public_key_tests {

    const KEYPAIR: [u8; 64] = [
        14, 206, 93, 54, 79, 221, 151, 197, 84, 158, 215, 171, 115, 97, 58, 53, 87, 127, 189, 113,
        11, 146, 146, 121, 253, 96, 36, 197, 212, 224, 116, 30, 246, 19, 75, 34, 193, 84, 183, 255,
        190, 28, 118, 154, 2, 111, 203, 103, 119, 178, 122, 11, 3, 96, 156, 47, 142, 207, 83, 173,
        129, 103, 108, 92,
    ];

    #[test]
    fn is_signer() {
        use crate::{Utilities, WasmiumOutcome, WasmiumSignature};

        let message = b"Foo Bar";
        let keypair = Utilities::array_to_ed25519_keypair(KEYPAIR).unwrap();

        use ed25519_dalek::Signer;
        let signature = keypair.sign(message);
        let public_key = keypair.public;

        let mut sig = WasmiumSignature::default();
        sig.add_message(message);
        sig.add_public_key(*public_key.as_bytes()).unwrap();
        sig.add_signature(signature.to_bytes()).unwrap();

        assert_eq!(WasmiumOutcome::ValidSignature, sig.verify_signature());
    }
}