Solitaire

Struct Solitaire 

Source
pub struct Solitaire { /* private fields */ }
Expand description

A Solitaire cipher implementation using a 54-card deck.

The Solitaire struct maintains the state of a deck of cards used for encryption and decryption operations. It stores both the initial deck configuration (for resetting between operations) and the current deck state (which is modified during keystream generation).

§Structure

  • initial_deck: The original deck configuration, preserved for resetting
  • deck: The working deck state, wrapped in RefCell for interior mutability

§Thread Safety

This type is not thread-safe due to the use of RefCell. Each thread should create its own instance if parallel encryption/decryption is needed.

§Examples

use old_crypto_rs::Solitaire;
use old_crypto_rs::Block;

// Create with default unkeyed deck
let cipher = Solitaire::new_unkeyed();

// Create with a passphrase
let cipher = Solitaire::new_with_passphrase("SECRET");

// Create with custom deck
let custom_deck: Vec<u8> = (1..=54).collect();
let cipher = Solitaire::new(custom_deck);

Implementations§

Source§

impl Solitaire

Source

pub fn new(deck: Vec<u8>) -> Self

Creates a new Solitaire cipher with a custom deck configuration.

The deck must be a permutation of 54 cards:

  • Cards 1-52: Standard playing cards (1-13 = Clubs, 14-26 = Diamonds, 27-39 = Hearts, 40-52 = Spades)
  • Card 53: Joker A
  • Card 54: Joker B
§Arguments
  • deck - A vector of exactly 54 unique bytes representing the deck order
§Panics

Panics if the deck length is not exactly 54 cards.

§Examples
use old_crypto_rs::Solitaire;

// Create with a custom deck order
let mut custom_deck: Vec<u8> = (1..=54).collect();
// Shuffle or reorder as needed
let cipher = Solitaire::new(custom_deck);
Source

pub fn new_unkeyed() -> Self

Creates a Solitaire cipher with an unkeyed (sorted) deck.

This initializes the deck in standard order (1, 2, 3, …, 54). An unkeyed deck provides no security and is primarily used for testing and demonstrating the algorithm’s operation.

§Examples
use old_crypto_rs::Solitaire;
use old_crypto_rs::Block;

let cipher = Solitaire::new_unkeyed();
let mut output = vec![0u8; 5];
cipher.encrypt(&mut output, b"HELLO");
§Security Warning

Never use an unkeyed deck for actual encryption as it provides no security.

Source

pub fn new_with_passphrase(passphrase: &str) -> Self

Creates a Solitaire cipher with a deck keyed by a passphrase.

The passphrase is used to shuffle the initially sorted deck through a series of deck transformations. Each alphabetic character in the passphrase (case-insensitive) contributes to the deck’s final permutation. Non-alphabetic characters are ignored.

§Arguments
  • passphrase - A string used to key the deck. Only ASCII alphabetic characters are processed; all others are skipped.
§Algorithm

For each alphabetic character in the passphrase:

  1. Convert to uppercase and get its position (A=1, B=2, …, Z=26)
  2. Advance the deck through one complete cycle (steps 1-4)
  3. Perform a count cut using the character’s numeric value
§Examples
use old_crypto_rs::Solitaire;
use old_crypto_rs::Block;

// Passphrase can contain spaces and punctuation (ignored)
let cipher = Solitaire::new_with_passphrase("My Secret Key!");

// Same as above (non-alpha characters ignored)
let cipher2 = Solitaire::new_with_passphrase("MYSECRETKEY");

Trait Implementations§

Source§

impl Block for Solitaire

Source§

fn encrypt(&self, dst: &mut [u8], src: &[u8]) -> usize

Encrypts plaintext using the Solitaire cipher algorithm.

This method generates a keystream by advancing the deck state and combines it with the plaintext to produce ciphertext. The deck is reset to its initial state before encryption begins, ensuring consistent keystream generation.

§Arguments
  • dst - A mutable byte slice where the encrypted output will be written. Must be at least as long as src.
  • src - A byte slice containing the plaintext to encrypt. Only ASCII alphabetic characters are encrypted; all others pass through unchanged.
§Returns

The number of bytes written to dst (always equal to src.len()).

§Algorithm

For each character in the source:

  • If alphabetic: Convert to uppercase, generate keystream byte, add values (mod 26)
  • If non-alphabetic: Copy unchanged to destination

The encryption formula is: C = (P + K - 1) mod 26 + 1, where:

  • P is the plaintext character value (A=1, B=2, …, Z=26)
  • K is the keystream value (1-26)
  • C is the resulting ciphertext character value
§Examples
use old_crypto_rs::Solitaire;
use old_crypto_rs::Block;

let cipher = Solitaire::new_unkeyed();
let plaintext = b"HELLO";
let mut ciphertext = vec![0u8; plaintext.len()];
cipher.encrypt(&mut ciphertext, plaintext);
// ciphertext now contains the encrypted result
§Notes
  • Input case is normalized to uppercase
  • Non-alphabetic characters (spaces, punctuation, digits) are preserved as-is
  • The deck is reset before encryption, so multiple calls produce the same output
Source§

fn decrypt(&self, dst: &mut [u8], src: &[u8]) -> usize

Decrypts ciphertext using the Solitaire cipher algorithm.

This method generates the same keystream used during encryption and subtracts it from the ciphertext to recover the original plaintext. The deck is reset to its initial state before decryption begins, ensuring the keystream matches encryption.

§Arguments
  • dst - A mutable byte slice where the decrypted output will be written. Must be at least as long as src.
  • src - A byte slice containing the ciphertext to decrypt. Only ASCII alphabetic characters are decrypted; all others pass through unchanged.
§Returns

The number of bytes written to dst (always equal to src.len()).

§Algorithm

For each character in the source:

  • If alphabetic: Convert to uppercase, generate keystream byte, subtract values (mod 26)
  • If non-alphabetic: Copy unchanged to destination

The decryption formula is: P = (C - K) mod 26, where:

  • C is the ciphertext character value (A=1, B=2, …, Z=26)
  • K is the keystream value (1-26)
  • P is the resulting plaintext character value

Special handling ensures proper modulo arithmetic for negative results.

§Examples
use old_crypto_rs::Solitaire;
use old_crypto_rs::Block;

let cipher = Solitaire::new_unkeyed();
let ciphertext = b"EXKYI";
let mut plaintext = vec![0u8; ciphertext.len()];
cipher.decrypt(&mut plaintext, ciphertext);
assert_eq!(&plaintext, b"AAAAA");
§Notes
  • Must use the same deck configuration (initial state) as encryption
  • Input case is normalized to uppercase
  • Non-alphabetic characters are preserved unchanged
  • The deck is reset before decryption to generate the correct keystream
Source§

fn block_size(&self) -> usize

Source§

impl Clone for Solitaire

Source§

fn clone(&self) -> Solitaire

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

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> 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.