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 resettingdeck: The working deck state, wrapped inRefCellfor 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
impl Solitaire
Sourcepub fn new(deck: Vec<u8>) -> Self
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);Sourcepub fn new_unkeyed() -> Self
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.
Sourcepub fn new_with_passphrase(passphrase: &str) -> Self
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:
- Convert to uppercase and get its position (A=1, B=2, …, Z=26)
- Advance the deck through one complete cycle (steps 1-4)
- 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
impl Block for Solitaire
Source§fn encrypt(&self, dst: &mut [u8], src: &[u8]) -> usize
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 assrc.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
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 assrc.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