Struct IronShieldChallenge

Source
pub struct IronShieldChallenge {
    pub random_nonce: String,
    pub created_time: i64,
    pub expiration_time: i64,
    pub website_id: String,
    pub challenge_param: [u8; 32],
    pub recommended_attempts: u64,
    pub public_key: [u8; 32],
    pub challenge_signature: [u8; 64],
}
Expand description

IronShield Challenge structure for the proof-of-work algorithm

  • random_nonce: The SHA-256 hash of a random number (hex string).
  • created_time: Unix milli timestamp for the challenge.
  • expiration_time: Unix milli timestamp for the challenge expiration time.
  • challenge_param: Target threshold - hash must be less than this value.
  • recommended_attempts: Expected number of attempts for user guidance (3x difficulty).
  • website_id: The identifier of the website.
  • public_key: Ed25519 public key for signature verification.
  • challenge_signature: Ed25519 signature over the challenge data.

Fields§

§random_nonce: String§created_time: i64§expiration_time: i64§website_id: String§challenge_param: [u8; 32]§recommended_attempts: u64§public_key: [u8; 32]§challenge_signature: [u8; 64]

Implementations§

Source§

impl IronShieldChallenge

Source

pub fn new( website_id: String, difficulty: u64, private_key: SigningKey, public_key: [u8; 32], ) -> Self

Constructor for creating a new IronShieldChallenge instance.

This function creates a new challenge and automatically generates a cryptographic signature using the provided private key. The signature covers all challenge data to prevent tampering.

§Arguments
  • website_id: The identifier of the website.
  • difficulty: The target difficulty (expected number of attempts).
  • private_key: Ed25519 private key for signing the challenge.
  • public_key: Ed25519 public key corresponding to the private key.
§Returns
  • Self: A new, properly signed IronShieldChallenge.
Source

pub fn difficulty_to_challenge_param(difficulty: u64) -> [u8; 32]

Converts a difficulty value (expected number of attempts) to a challenge_param.

The difficulty represents the expected number of hash attempts needed to find a valid nonce where SHA256(random_nonce_bytes + nonce_bytes) < challenge_param.

Since hash outputs are uniformly distributed over the 256-bit space, the relationship is: challenge_param = 2^256 / difficulty.

This function accurately calculates this for difficulties ranging from 1 to u64::MAX.

§Arguments
  • difficulty: Expected number of attempts (must be > 0).
§Returns
  • [u8; 32]: The challenge_param bytes in big-endian format.
§Panics
  • Panics if difficulty is 0
§Examples
  • difficulty = 1 -> challenge_param = [0xFF; 32] (very easy, ~100% chance).
  • difficulty = 2 -> challenge_param = [0x80, 0x00, …] (MSB set, ~50% chance).
  • difficulty = 10,000 -> challenge_param ≈ 2^242.7 (realistic difficulty).
  • difficulty = 1,000,000 -> challenge_param ≈ 2^236.4 (higher difficulty).
Source

pub fn is_expired(&self) -> bool

§Returns
  • bool: true if the challenge is expired, false otherwise.
Source

pub fn time_until_expiration(&self) -> i64

§Returns
  • i64: created_time plus 30 seconds.
Source

pub fn generate_created_time() -> i64

§Returns
  • i64: The current time in millis.
Source

pub fn generate_random_nonce() -> String

§Returns
  • String: A random hex-encoded value.
Source

pub fn recommended_attempts(difficulty: u64) -> u64

Returns the recommended number of attempts to expect for a given difficulty.

This provides users with a realistic expectation of how many attempts they might need. Since the expected value is equal to the difficulty, we return 2x the difficulty to give users a reasonable upper bound for planning purposes.

§Arguments
  • difficulty: The target difficulty (expected number of attempts)
§Returns
  • u64: Recommended number of attempts (2x the difficulty)
§Examples
  • difficulty = 1,000 → recommended_attempts = 2,000
  • difficulty = 50,000 → recommended_attempts = 100,000
Source

pub fn concat_struct(&self) -> String

Concatenates the challenge data into a string.

Concatenates:

  • random_nonce as a string.
  • created_time as i64.
  • expiration_time as i64.
  • website_id as a string.
  • public_key as a lowercase hex string.
  • challenge_params as a lowercase hex string.
Source

pub fn from_concat_struct(concat_str: &str) -> Result<Self, String>

Creates an IronShieldChallenge from a concatenated string.

This function reverses the operation of IronShieldChallenge::concat_struct. Expects a string in the format: “random_nonce|created_time|expiration_time|website_id|challenge_params|public_key|challenge_signature”

§Arguments
  • concat_str: The concatenated string to parse, typically generated by concat_struct().
§Returns
  • Result<Self, String>: A result containing the parsed IronShieldChallenge or an error message if parsing fails.
Source

pub fn to_base64url_header(&self) -> String

Encodes the challenge as a base64url string for HTTP header transport.

This method concatenates all challenge fields using the established | delimiter format, and then base64url-encodes the result for safe transport in HTTP headers.

§Returns
  • String: Base64url-encoded string ready for HTTP header use.
§Example
use ironshield_types::IronShieldChallenge;
use ed25519_dalek::SigningKey;
let dummy_key = SigningKey::from_bytes(&[0u8; 32]);
let challenge = IronShieldChallenge::new(
    "test_website".to_string(),
    100_000,
    dummy_key,
    [0x34; 32],
);
let header_value = challenge.to_base64url_header();
// Use header_value in HTTP header: "X-IronShield-Challenge-Data: {header_value}"
Source

pub fn from_base64url_header(encoded_header: &str) -> Result<Self, String>

Decodes a base64url-encoded challenge from an HTTP header.

This method reverses the to_base64url_header() operation by first base64url-decoding the input string and then parsing it using the established | delimiter format.

§Arguments
  • encoded_header: The base64url-encoded string from the HTTP header.
§Returns
  • Result<Self, String>: Decoded challenge or detailed error message.
§Example
use ironshield_types::IronShieldChallenge;
use ed25519_dalek::SigningKey;
// Create a challenge and encode it
let dummy_key = SigningKey::from_bytes(&[0u8; 32]);
let original = IronShieldChallenge::new(
    "test_website".to_string(),
    100_000,
    dummy_key,
    [0x34; 32],
);
let header_value = original.to_base64url_header();
// Decode it back
let decoded = IronShieldChallenge::from_base64url_header(&header_value).unwrap();
assert_eq!(original.random_nonce, decoded.random_nonce);

Trait Implementations§

Source§

impl Clone for IronShieldChallenge

Source§

fn clone(&self) -> IronShieldChallenge

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for IronShieldChallenge

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for IronShieldChallenge

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for IronShieldChallenge

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,