/* * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ /*! This module provides a Rust wrapper for the wolfCrypt library's EdDSA Curve 25519 (Ed25519) functionality. */ #![cfg(ed25519)] use crate::sys; use crate::random::RNG; use core::mem::MaybeUninit; /// The `Ed25519` struct manages the lifecycle of a wolfSSL `ed25519_key` /// object. /// /// It ensures proper initialization and deallocation. /// /// An instance can be created with `generate()` or `new()`. pub struct Ed25519 { ws_key: sys::ed25519_key, } impl Ed25519 { /** Size of private key only. */ pub const KEY_SIZE: usize = sys::ED25519_KEY_SIZE as usize; /** Size of signature. */ pub const SIG_SIZE: usize = sys::ED25519_SIG_SIZE as usize; /** Compressed public key size. */ pub const PUB_KEY_SIZE: usize = sys::ED25519_PUB_KEY_SIZE as usize; /** Size of both private and public key. */ pub const PRV_KEY_SIZE: usize = sys::ED25519_PRV_KEY_SIZE as usize; pub const ED25519: u8 = sys::Ed25519 as u8; pub const ED25519CTX: u8 = sys::Ed25519ctx as u8; pub const ED25519PH: u8 = sys::Ed25519ph as u8; /// Generate a new Ed25519 key. /// /// # Parameters /// /// * `rng`: `RNG` instance to use for random number generation. /// /// # Returns /// /// Returns either Ok(ed25519) containing the Ed25519 struct instance or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// ``` pub fn generate(rng: &mut RNG) -> Result { Self::generate_ex(rng, None, None) } /// Generate a new Ed25519 key with optional heap and device ID. /// /// # Parameters /// /// * `rng`: `RNG` instance to use for random number generation. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ed25519) containing the Ed25519 struct instance or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate_ex(&mut rng, None, None).expect("Error with generate_ex()"); /// ``` pub fn generate_ex(rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut ws_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ed25519_init_ex(ws_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let ws_key = unsafe { ws_key.assume_init() }; let mut ed25519 = Ed25519 { ws_key }; let rc = unsafe { sys::wc_ed25519_make_key(&mut rng.wc_rng, sys::ED25519_KEY_SIZE as i32, &mut ed25519.ws_key) }; if rc != 0 { return Err(rc); } Ok(ed25519) } /// Create and initialize a new Ed25519 instance. /// /// A key will not be present but can be imported with one of the import /// functions. /// /// # Returns /// /// Returns either Ok(ed25519) containing the Ed25519 struct instance or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let ed = Ed25519::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Create and initialize a new Ed25519 instance with optional heap and /// device ID. /// /// A key will not be present but can be imported with one of the import /// functions. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ed25519) containing the Ed25519 struct instance or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let ed = Ed25519::new_ex(None, None).expect("Error with new()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut ws_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ed25519_init_ex(ws_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let ws_key = unsafe { ws_key.assume_init() }; let ed25519 = Ed25519 { ws_key }; Ok(ed25519) } /// Check the public key is valid. /// /// When a private key is present, check that the calculated public key /// matches it. When a private key is not present, check that Y is in range /// and an X is able to be calculated. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// ed.check_key().expect("Error with check_key()"); /// ``` pub fn check_key(&mut self) -> Result<(), i32> { let rc = unsafe { sys::wc_ed25519_check_key(&mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export private and public key to separate buffers. /// /// # Parameters /// /// * `private`: Output buffer in which to store the public/private key /// pair. The length should be PRV_KEY_SIZE. /// * `public`: Output buffer in which to store the public key. The length /// should be PUB_KEY_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_export)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::PRV_KEY_SIZE]; /// let mut public = [0u8; Ed25519::PUB_KEY_SIZE]; /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); /// } /// ``` #[cfg(ed25519_export)] pub fn export_key(&self, private: &mut [u8], public: &mut [u8]) -> Result<(), i32> { let mut private_size = crate::buffer_len_to_u32(private.len())?; let mut public_size = crate::buffer_len_to_u32(public.len())?; let rc = unsafe { sys::wc_ed25519_export_key(&self.ws_key, private.as_mut_ptr(), &mut private_size, public.as_mut_ptr(), &mut public_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export public key to buffer. /// /// # Parameters /// /// * `public`: Output buffer in which to store the public key. The length /// should be PUB_KEY_SIZE. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `public` on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_export)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut public = [0u8; Ed25519::PUB_KEY_SIZE]; /// ed.export_public(&mut public).expect("Error with export_public()"); /// } /// ``` #[cfg(ed25519_export)] pub fn export_public(&self, public: &mut [u8]) -> Result<(), i32> { let mut public_size = crate::buffer_len_to_u32(public.len())?; let rc = unsafe { sys::wc_ed25519_export_public(&self.ws_key, public.as_mut_ptr(), &mut public_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export public/private key pair to buffer. /// /// # Parameters /// /// * `keyout`: Output buffer in which to store the key pair. The length /// should be PRV_KEY_SIZE. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `keyout` on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_export)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::PRV_KEY_SIZE]; /// ed.export_private(&mut private).expect("Error with export_private()"); /// } /// ``` #[cfg(ed25519_export)] pub fn export_private(&self, keyout: &mut [u8]) -> Result<(), i32> { let mut keyout_size = crate::buffer_len_to_u32(keyout.len())?; let rc = unsafe { sys::wc_ed25519_export_private(&self.ws_key, keyout.as_mut_ptr(), &mut keyout_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export private key only to buffer. /// /// # Parameters /// /// * `private`: Output buffer in which to store the private key. The /// length should be KEY_SIZE. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `private` on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_export)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private_only = [0u8; Ed25519::KEY_SIZE]; /// ed.export_private_only(&mut private_only).expect("Error with export_private_only()"); /// } /// ``` #[cfg(ed25519_export)] pub fn export_private_only(&self, private: &mut [u8]) -> Result<(), i32> { let mut private_size = crate::buffer_len_to_u32(private.len())?; let rc = unsafe { sys::wc_ed25519_export_private_only(&self.ws_key, private.as_mut_ptr(), &mut private_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Import a public Ed25519 key from buffer. /// /// This function handles either compressed or uncompressed keys. /// The public key is checked that it matches the private key if one is /// already present. /// /// # Parameters /// /// * `public`: Input buffer containing public key. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_import)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::PRV_KEY_SIZE]; /// let mut public = [0u8; Ed25519::PUB_KEY_SIZE]; /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); /// let mut ed = Ed25519::new().expect("Error with new()"); /// ed.import_public(&public).expect("Error with import_public()"); /// } /// ``` #[cfg(ed25519_import)] pub fn import_public(&mut self, public: &[u8]) -> Result<(), i32> { let public_size = crate::buffer_len_to_u32(public.len())?; let rc = unsafe { sys::wc_ed25519_import_public(public.as_ptr(), public_size, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(()) } /// Import a public Ed25519 key from buffer with trusted flag. /// /// This function handles either compressed or uncompressed keys. /// The public key is checked that it matches the private key if one is /// already present and trusted is false. /// /// # Parameters /// /// * `public`: Input buffer containing public key. /// * `trusted`: Whether the public key buffer is trusted. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_import)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::PRV_KEY_SIZE]; /// let mut public = [0u8; Ed25519::PUB_KEY_SIZE]; /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); /// let mut ed = Ed25519::new().expect("Error with new()"); /// ed.import_public_ex(&public, false).expect("Error with import_public_ex()"); /// } /// ``` #[cfg(ed25519_import)] pub fn import_public_ex(&mut self, public: &[u8], trusted: bool) -> Result<(), i32> { let public_size = crate::buffer_len_to_u32(public.len())?; let rc = unsafe { sys::wc_ed25519_import_public_ex(public.as_ptr(), public_size, &mut self.ws_key, if trusted {1} else {0}) }; if rc != 0 { return Err(rc); } Ok(()) } /// Import private Ed25519 key only from buffer. /// /// # Parameters /// /// * `private`: Input buffer containing private key. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_import)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private_only = [0u8; Ed25519::KEY_SIZE]; /// ed.export_private_only(&mut private_only).expect("Error with export_private_only()"); /// let mut ed = Ed25519::new().expect("Error with new()"); /// ed.import_private_only(&private_only).expect("Error with import_private_only()"); /// } /// ``` #[cfg(ed25519_import)] pub fn import_private_only(&mut self, private: &[u8]) -> Result<(), i32> { let private_size = crate::buffer_len_to_u32(private.len())?; let rc = unsafe { sys::wc_ed25519_import_private_only(private.as_ptr(), private_size, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(()) } /// Import public/private Ed25519 key pair from buffers. /// /// This functions handles either compressed or uncompressed keys. /// The public key is assumed to be untrusted and is checked against the /// private key. /// /// # Parameters /// /// * `private`: Input buffer containing private key. /// * `public`: Optional input buffer containing public key. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_import)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::PRV_KEY_SIZE]; /// let mut public = [0u8; Ed25519::PUB_KEY_SIZE]; /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); /// let mut ed = Ed25519::new().expect("Error with new()"); /// ed.import_private_key(&private, Some(&public)).expect("Error with import_private_key()"); /// } /// ``` #[cfg(ed25519_import)] pub fn import_private_key(&mut self, private: &[u8], public: Option<&[u8]>) -> Result<(), i32> { let private_size = crate::buffer_len_to_u32(private.len())?; let mut public_ptr: *const u8 = core::ptr::null(); let mut public_size = 0u32; if let Some(public) = public { public_ptr = public.as_ptr(); public_size = crate::buffer_len_to_u32(public.len())?; } let rc = unsafe { sys::wc_ed25519_import_private_key(private.as_ptr(), private_size, public_ptr, public_size, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(()) } /// Import public/private Ed25519 key pair from buffers with trusted flag. /// /// This functions handles either compressed or uncompressed keys. /// The public is checked against private key if not trusted. /// /// # Parameters /// /// * `private`: Input buffer containing private key. /// * `public`: Optional input buffer containing private key. /// * `trusted`: Whether the public key buffer is trusted. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_import)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::PRV_KEY_SIZE]; /// let mut public = [0u8; Ed25519::PUB_KEY_SIZE]; /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); /// let mut ed = Ed25519::new().expect("Error with new()"); /// ed.import_private_key_ex(&private, Some(&public), false).expect("Error with import_private_key_ex()"); /// } /// ``` #[cfg(ed25519_import)] pub fn import_private_key_ex(&mut self, private: &[u8], public: Option<&[u8]>, trusted: bool) -> Result<(), i32> { let private_size = crate::buffer_len_to_u32(private.len())?; let mut public_ptr: *const u8 = core::ptr::null(); let mut public_size = 0u32; if let Some(public) = public { public_ptr = public.as_ptr(); public_size = crate::buffer_len_to_u32(public.len())?; } let rc = unsafe { sys::wc_ed25519_import_private_key_ex(private.as_ptr(), private_size, public_ptr, public_size, &mut self.ws_key, if trusted {1} else {0}) }; if rc != 0 { return Err(rc); } Ok(()) } /// Generate the Ed25519 public key from the private key stored in the /// Ed25519 object. /// /// The public key is written to the pubkey output buffer. /// /// # Parameters /// /// * `pubkey`: Output buffer in which to store the public key. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let mut private = [0u8; Ed25519::KEY_SIZE]; /// ed.export_private_only(&mut private).expect("Error with export_private_only()"); /// let mut ed = Ed25519::new().expect("Error with new()"); /// ed.import_private_only(&private).expect("Error with import_private_only()"); /// let mut public = [0u8; Ed25519::KEY_SIZE]; /// ed.make_public(&mut public).expect("Error with make_public()"); /// ``` pub fn make_public(&mut self, pubkey: &mut [u8]) -> Result<(), i32> { let pubkey_size = crate::buffer_len_to_u32(pubkey.len())?; let rc = unsafe { sys::wc_ed25519_make_public(&mut self.ws_key, pubkey.as_mut_ptr(), pubkey_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Sign a message using Ed25519 key. /// /// # Parameters /// /// * `message`: Message to sign. /// * `signature`: Output buffer to hold signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// signature on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_sign)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()"); /// } /// ``` #[cfg(ed25519_sign)] pub fn sign_msg(&mut self, message: &[u8], signature: &mut [u8]) -> Result { let message_size = crate::buffer_len_to_u32(message.len())?; let mut signature_size = crate::buffer_len_to_u32(signature.len())?; let rc = unsafe { sys::wc_ed25519_sign_msg(message.as_ptr(), message_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(signature_size as usize) } /// Sign a message with context using Ed25519 key. /// /// The context is part of the data signed. /// /// # Parameters /// /// * `message`: Message to sign. /// * `context`: Buffer containing context for which message is being signed. /// * `signature`: Output buffer to hold signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// signature on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_sign)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg_ctx(&message, context, &mut signature).expect("Error with sign_msg_ctx()"); /// } /// ``` #[cfg(ed25519_sign)] pub fn sign_msg_ctx(&mut self, message: &[u8], context: &[u8], signature: &mut [u8]) -> Result { let message_size = crate::buffer_len_to_u32(message.len())?; if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } let context_size = context.len() as u8; let mut signature_size = crate::buffer_len_to_u32(signature.len())?; let rc = unsafe { sys::wc_ed25519ctx_sign_msg(message.as_ptr(), message_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key, context.as_ptr(), context_size) }; if rc != 0 { return Err(rc); } Ok(signature_size as usize) } /// Sign a message digest with context using Ed25519 key. /// /// The context is part of the data signed. /// The message is pre-hashed before signature calculation. /// /// # Parameters /// /// * `hash`: Message digest to sign. /// * `context`: Optional buffer containing context for which hash is being signed. /// * `signature`: Output buffer to hold signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// signature on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_sign)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let hash = [ /// 0xddu8,0xaf,0x35,0xa1,0x93,0x61,0x7a,0xba, /// 0xcc,0x41,0x73,0x49,0xae,0x20,0x41,0x31, /// 0x12,0xe6,0xfa,0x4e,0x89,0xa9,0x7e,0xa2, /// 0x0a,0x9e,0xee,0xe6,0x4b,0x55,0xd3,0x9a, /// 0x21,0x92,0x99,0x2a,0x27,0x4f,0xc1,0xa8, /// 0x36,0xba,0x3c,0x23,0xa3,0xfe,0xeb,0xbd, /// 0x45,0x4d,0x44,0x23,0x64,0x3c,0xe8,0x0e, /// 0x2a,0x9a,0xc9,0x4f,0xa5,0x4c,0xa4,0x9f /// ]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_hash_ph(&hash, Some(context), &mut signature).expect("Error with sign_hash_ph()"); /// } /// ``` #[cfg(ed25519_sign)] pub fn sign_hash_ph(&mut self, hash: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { let hash_size = crate::buffer_len_to_u32(hash.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let mut signature_size = crate::buffer_len_to_u32(signature.len())?; let rc = unsafe { sys::wc_ed25519ph_sign_hash(hash.as_ptr(), hash_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(signature_size as usize) } /// Sign a message with context using Ed25519 key. /// /// The context is part of the data signed. /// The message is pre-hashed before signature calculation. /// /// # Parameters /// /// * `message`: Message digest to sign. /// * `context`: Optional buffer containing context for which message is being signed. /// * `signature`: Output buffer to hold signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// signature on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_sign)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg_ph(&message, Some(context), &mut signature).expect("Error with sign_msg_ph()"); /// } /// ``` #[cfg(ed25519_sign)] pub fn sign_msg_ph(&mut self, message: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { let message_size = crate::buffer_len_to_u32(message.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let mut signature_size = crate::buffer_len_to_u32(signature.len())?; let rc = unsafe { sys::wc_ed25519ph_sign_msg(message.as_ptr(), message_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(signature_size as usize) } /// Sign input data with optional context using Ed25519 key. /// /// If provided, the context is part of the data signed. /// /// # Parameters /// /// * `din`: Data to sign. /// * `context`: Optional buffer containing context for which `din` is being signed. /// * `typ`: One of `Ed25519::ED25519`, `Ed25519::ED25519CTX`, or `Ed25519::ED25519PH`. /// * `signature`: Output buffer to hold signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// signature on success or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_sign)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg_ex(&message, Some(context), Ed25519::ED25519, &mut signature).expect("Error with sign_msg_ex()"); /// } /// ``` #[cfg(ed25519_sign)] pub fn sign_msg_ex(&mut self, din: &[u8], context: Option<&[u8]>, typ: u8, signature: &mut [u8]) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let mut signature_size = crate::buffer_len_to_u32(signature.len())?; let rc = unsafe { sys::wc_ed25519_sign_msg_ex(din.as_ptr(), din_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key, typ, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(signature_size as usize) } /// Verify the Ed25519 signature of a message to ensure authenticity. /// /// # Parameters /// /// * `signature`: Signature to verify. /// * `message`: Message to verify the signature of. /// /// # Returns /// /// Returns either Ok(valid) containing whether the signature is valid or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()"); /// let signature_valid = ed.verify_msg(&signature, &message).expect("Error with verify_msg()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_verify)] pub fn verify_msg(&mut self, signature: &[u8], message: &[u8]) -> Result { let signature_size = crate::buffer_len_to_u32(signature.len())?; let message_size = crate::buffer_len_to_u32(message.len())?; let mut res = 0i32; let rc = unsafe { sys::wc_ed25519_verify_msg(signature.as_ptr(), signature_size, message.as_ptr(), message_size, &mut res, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(res == 1) } /// Verify the Ed25519 signature of a message and context to ensure authenticity. /// /// The context is included as part of the data verified. /// /// # Parameters /// /// * `signature`: Signature to verify. /// * `message`: Message to verify the signature of. /// * `context`: Buffer containing context for which the message was signed. /// /// # Returns /// /// Returns either Ok(valid) containing whether the signature is valid or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = b"Hello!"; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg_ctx(message, context, &mut signature).expect("Error with sign_msg()"); /// let signature_valid = ed.verify_msg_ctx(&signature, message, context).expect("Error with verify_msg_ctx()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_verify)] pub fn verify_msg_ctx(&mut self, signature: &[u8], message: &[u8], context: &[u8]) -> Result { let signature_size = crate::buffer_len_to_u32(signature.len())?; let message_size = crate::buffer_len_to_u32(message.len())?; if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } let context_size = context.len() as u8; let mut res = 0i32; let rc = unsafe { sys::wc_ed25519ctx_verify_msg(signature.as_ptr(), signature_size, message.as_ptr(), message_size, &mut res, &mut self.ws_key, context.as_ptr(), context_size) }; if rc != 0 { return Err(rc); } Ok(res == 1) } /// Verify the Ed25519 signature of a message digest and context to ensure authenticity. /// /// The context is included as part of the data verified. /// The hash algorithm used to create message digest must be SHA-512. /// The message is pre-hashed before verification. /// /// # Parameters /// /// * `signature`: Signature to verify. /// * `hash`: Message to verify the signature of. /// * `context`: Optional buffer containing context for which the hash was signed. /// /// # Returns /// /// Returns either Ok(valid) containing whether the signature is valid or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let hash = [ /// 0xddu8,0xaf,0x35,0xa1,0x93,0x61,0x7a,0xba, /// 0xcc,0x41,0x73,0x49,0xae,0x20,0x41,0x31, /// 0x12,0xe6,0xfa,0x4e,0x89,0xa9,0x7e,0xa2, /// 0x0a,0x9e,0xee,0xe6,0x4b,0x55,0xd3,0x9a, /// 0x21,0x92,0x99,0x2a,0x27,0x4f,0xc1,0xa8, /// 0x36,0xba,0x3c,0x23,0xa3,0xfe,0xeb,0xbd, /// 0x45,0x4d,0x44,0x23,0x64,0x3c,0xe8,0x0e, /// 0x2a,0x9a,0xc9,0x4f,0xa5,0x4c,0xa4,0x9f /// ]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_hash_ph(&hash, Some(context), &mut signature).expect("Error with sign_hash_ph()"); /// let signature_valid = ed.verify_hash_ph(&signature, &hash, Some(context)).expect("Error with verify_hash_ph()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_verify)] pub fn verify_hash_ph(&mut self, signature: &[u8], hash: &[u8], context: Option<&[u8]>) -> Result { let signature_size = crate::buffer_len_to_u32(signature.len())?; let hash_size = crate::buffer_len_to_u32(hash.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let mut res = 0i32; let rc = unsafe { sys::wc_ed25519ph_verify_hash(signature.as_ptr(), signature_size, hash.as_ptr(), hash_size, &mut res, &mut self.ws_key, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(res == 1) } /// Verify the Ed25519 signature of a message and context to ensure authenticity. /// /// The context is included as part of the data verified. /// The message is pre-hashed before verification. /// /// # Parameters /// /// * `signature`: Signature to verify. /// * `message`: Message to verify the signature of. /// * `context`: Option buffer containing context for which the message was signed. /// /// # Returns /// /// Returns either Ok(valid) containing whether the signature is valid or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg_ph(&message, Some(context), &mut signature).expect("Error with sign_msg_ph()"); /// let signature_valid = ed.verify_msg_ph(&signature, &message, Some(context)).expect("Error with verify_msg_ph()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_verify)] pub fn verify_msg_ph(&mut self, signature: &[u8], message: &[u8], context: Option<&[u8]>) -> Result { let signature_size = crate::buffer_len_to_u32(signature.len())?; let message_size = crate::buffer_len_to_u32(message.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let mut res = 0i32; let rc = unsafe { sys::wc_ed25519ph_verify_msg(signature.as_ptr(), signature_size, message.as_ptr(), message_size, &mut res, &mut self.ws_key, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(res == 1) } /// Verify the Ed25519 signature of a message and context to ensure authenticity. /// /// The context is included as part of the data verified. /// /// # Parameters /// /// * `signature`: Signature to verify. /// * `din`: Message to verify the signature of. /// * `context`: Optional buffer containing context for which the input data was signed. /// * `typ`: One of `Ed25519::ED25519`, `Ed25519::ED25519CTX`, or `Ed25519::ED25519PH`. /// /// # Returns /// /// Returns either Ok(valid) containing whether the signature is valid or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg_ex(&message, Some(context), Ed25519::ED25519, &mut signature).expect("Error with sign_msg_ex()"); /// let signature_valid = ed.verify_msg_ex(&signature, &message, Some(context), Ed25519::ED25519).expect("Error with verify_msg_ex()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_verify)] pub fn verify_msg_ex(&mut self, signature: &[u8], din: &[u8], context: Option<&[u8]>, typ: u8) -> Result { let signature_size = crate::buffer_len_to_u32(signature.len())?; let din_size = crate::buffer_len_to_u32(din.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let mut res = 0i32; let rc = unsafe { sys::wc_ed25519_verify_msg_ex(signature.as_ptr(), signature_size, din.as_ptr(), din_size, &mut res, &mut self.ws_key, typ, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(res == 1) } /// Initialize Ed25519 key to perform streaming verification. /// /// # Parameters /// /// * `signature`: Signature to verify. /// * `context`: Optional buffer containing context for which the input data was signed. /// * `typ`: One of `Ed25519::ED25519`, `Ed25519::ED25519CTX`, or `Ed25519::ED25519PH`. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_streaming_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()"); /// ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()"); /// ed.verify_msg_update(&message[0..2]).expect("Error with verify_msg_update()"); /// ed.verify_msg_update(&message[2..4]).expect("Error with verify_msg_update()"); /// let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_streaming_verify)] pub fn verify_msg_init(&mut self, signature: &[u8], context: Option<&[u8]>, typ: u8) -> Result<(), i32> { let signature_size = crate::buffer_len_to_u32(signature.len())?; let mut context_ptr: *const u8 = core::ptr::null(); let mut context_size = 0u8; if let Some(context) = context { context_ptr = context.as_ptr(); if context.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } context_size = context.len() as u8; } let rc = unsafe { sys::wc_ed25519_verify_msg_init(signature.as_ptr(), signature_size, &mut self.ws_key, typ, context_ptr, context_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Add input data to Ed25519 streaming verification. /// /// # Parameters /// /// * `din`: Segment of message to verify the signature of. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_streaming_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()"); /// ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()"); /// ed.verify_msg_update(&message[0..2]).expect("Error with verify_msg_update()"); /// ed.verify_msg_update(&message[2..4]).expect("Error with verify_msg_update()"); /// let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_streaming_verify)] pub fn verify_msg_update(&mut self, din: &[u8]) -> Result<(), i32> { let din_size = crate::buffer_len_to_u32(din.len())?; let rc = unsafe { sys::wc_ed25519_verify_msg_update(din.as_ptr(), din_size, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize Ed25519 streaming verification. /// /// # Parameters /// /// * `signature`: Signature to verify. /// /// # Returns /// /// Returns either Ok(valid) containing whether the signature is valid or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ed25519_streaming_verify)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let message = [0x42u8, 33, 55, 66]; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; /// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()"); /// ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()"); /// ed.verify_msg_update(&message[0..2]).expect("Error with verify_msg_update()"); /// ed.verify_msg_update(&message[2..4]).expect("Error with verify_msg_update()"); /// let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()"); /// assert!(signature_valid); /// } /// ``` #[cfg(ed25519_streaming_verify)] pub fn verify_msg_final(&mut self, signature: &[u8]) -> Result { let signature_size = crate::buffer_len_to_u32(signature.len())?; let mut res = 0i32; let rc = unsafe { sys::wc_ed25519_verify_msg_final(signature.as_ptr(), signature_size, &mut res, &mut self.ws_key) }; if rc != 0 { return Err(rc); } Ok(res == 1) } /// Get the size of an Ed25519 key (32 bytes). /// /// # Returns /// /// Returns either Ok(size) containing the key size or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let key_size = ed.size().expect("Error with size()"); /// assert_eq!(key_size, Ed25519::KEY_SIZE); /// ``` pub fn size(&self) -> Result { let rc = unsafe { sys::wc_ed25519_size(&self.ws_key) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Get the size of a private (including public) Ed25519 key (64 bytes). /// /// # Returns /// /// Returns either Ok(size) containing the key size or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let priv_size = ed.priv_size().expect("Error with priv_size()"); /// assert_eq!(priv_size, Ed25519::PRV_KEY_SIZE); /// ``` pub fn priv_size(&self) -> Result { let rc = unsafe { sys::wc_ed25519_priv_size(&self.ws_key) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Get the size of a public Ed25519 key (32 bytes). /// /// # Returns /// /// Returns either Ok(size) containing the key size or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let pub_size = ed.pub_size().expect("Error with pub_size()"); /// assert_eq!(pub_size, Ed25519::PUB_KEY_SIZE); /// ``` pub fn pub_size(&self) -> Result { let rc = unsafe { sys::wc_ed25519_pub_size(&self.ws_key) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Get the size of a Ed25519 signature (64 bytes). /// /// # Returns /// /// Returns either Ok(size) containing the key size or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ed25519::Ed25519; /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// let sig_size = ed.sig_size().expect("Error with sig_size()"); /// assert_eq!(sig_size, Ed25519::SIG_SIZE); /// ``` pub fn sig_size(&self) -> Result { let rc = unsafe { sys::wc_ed25519_sig_size(&self.ws_key) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } } impl Ed25519 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.ws_key); } } } impl Drop for Ed25519 { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_ed25519_free(&mut self.ws_key); } self.zeroize(); } } /// RustCrypto `signature` crate trait implementations. /// /// Provides a fixed-size [`Signature`] and a [`VerifyingKey`] type so that /// [`Ed25519`] can be used wherever the `signature` crate's /// [`signature::SignerMut`], [`signature::Keypair`], and /// [`signature::Verifier`] traits are accepted. #[cfg(feature = "signature")] mod signature_impl { use super::Ed25519; use signature::Error; /// Ed25519 signature in its standard 64-byte encoded form. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Signature([u8; Ed25519::SIG_SIZE]); impl Signature { /// Construct a signature from its raw bytes. pub const fn from_bytes(bytes: [u8; Ed25519::SIG_SIZE]) -> Self { Self(bytes) } /// Return the raw signature bytes. pub const fn to_bytes(&self) -> [u8; Ed25519::SIG_SIZE] { self.0 } } impl AsRef<[u8]> for Signature { fn as_ref(&self) -> &[u8] { &self.0 } } impl TryFrom<&[u8]> for Signature { type Error = Error; fn try_from(bytes: &[u8]) -> Result { let arr: [u8; Ed25519::SIG_SIZE] = bytes.try_into().map_err(|_| Error::new())?; Ok(Self(arr)) } } impl From for [u8; Ed25519::SIG_SIZE] { fn from(sig: Signature) -> Self { sig.0 } } impl signature::SignatureEncoding for Signature { type Repr = [u8; Ed25519::SIG_SIZE]; } /// Ed25519 verifying (public) key. /// /// Owns a copy of the 32-byte compressed public key and instantiates a /// short-lived wolfCrypt `ed25519_key` on each verification. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct VerifyingKey([u8; Ed25519::PUB_KEY_SIZE]); impl VerifyingKey { /// Construct a verifying key from its raw public key bytes. pub const fn from_bytes(bytes: [u8; Ed25519::PUB_KEY_SIZE]) -> Self { Self(bytes) } /// Return the raw public key bytes. pub const fn to_bytes(&self) -> [u8; Ed25519::PUB_KEY_SIZE] { self.0 } } impl AsRef<[u8]> for VerifyingKey { fn as_ref(&self) -> &[u8] { &self.0 } } impl TryFrom<&[u8]> for VerifyingKey { type Error = Error; fn try_from(bytes: &[u8]) -> Result { let arr: [u8; Ed25519::PUB_KEY_SIZE] = bytes.try_into().map_err(|_| Error::new())?; Ok(Self(arr)) } } #[cfg(all(ed25519_sign, ed25519_export))] impl signature::Keypair for Ed25519 { type VerifyingKey = VerifyingKey; fn verifying_key(&self) -> Self::VerifyingKey { let mut pub_key = [0u8; Ed25519::PUB_KEY_SIZE]; self.export_public(&mut pub_key).expect("ed25519 export_public failed"); VerifyingKey(pub_key) } } #[cfg(ed25519_sign)] impl signature::SignerMut for Ed25519 { fn try_sign(&mut self, msg: &[u8]) -> Result { let mut sig = [0u8; Ed25519::SIG_SIZE]; self.sign_msg(msg, &mut sig).map_err(|_| Error::new())?; Ok(Signature(sig)) } } #[cfg(all(ed25519_import, ed25519_verify))] impl signature::Verifier for VerifyingKey { fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> { let mut key = Ed25519::new().map_err(|_| Error::new())?; key.import_public(&self.0).map_err(|_| Error::new())?; let valid = key .verify_msg(&signature.0, msg) .map_err(|_| Error::new())?; if valid { Ok(()) } else { Err(Error::new()) } } } } #[cfg(feature = "signature")] pub use signature_impl::{Signature, VerifyingKey};