2个版本
0.0.2 | 2023年9月8日 |
---|---|
0.0.1 | 2023年9月8日 |
#1071 在 加密学
23KB
477 行
cardseed
cardseed crate提供解析和序列化扑克牌的功能。
在加密环境中,扑克牌可以用来编码和生成熵。一副随机洗好的52张扑克牌可以编码$52! \approx 2^{228}$种不同的组合。cardseed crate可以轻松地将现实世界中洗好的牌解析和转换为安全的伪随机数据,这些数据可以用来派生加密或签名密钥、随机数生成器的种子或其他类似的操作。
use cardseed::Deck;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let deck = "AS 3H KC 3C".parse::<Deck>()?;
let secret = deck.hash(Some("bestpasswordever"))?;
let expected = [35, 20, 205, 7, 35, 104, 123, 150, 57, 148, 101,
109, 151, 0, 87, 15, 103, 14, 67, 214, 165, 165,
44, 218, 5, 232, 30, 26, 100, 90, 169, 244];
assert_eq!(secret, expected);
Ok(())
}
扑克牌
扑克牌由两个字段组成:一个value
和一个suit
。value字段是一个u32
,对应于牌的面值减1(因为我们从零开始计数)。suit字段是一个cardseed::Suit
枚举成员,对应于四种扑克牌花色之一。
序列化时,Card表示为包含两个字符的字符串。第一个字符代表牌的面值,第二个字符代表花色。例如,"7H"
代表红桃7。
面值
字符 | 牌 | 值 |
---|---|---|
A |
Ace | 0 |
2 |
2 | 1 |
3 |
3 | 2 |
4 |
4 | 3 |
5 |
5 | 4 |
6 |
6 | 5 |
7 |
7 | 6 |
8 |
8 | 7 |
9 |
9 | 8 |
T |
Ten | 9 |
J |
Jack | 10 |
Q |
Queen | 11 |
K |
King | 12 |
花色
字符 | 花色 | 值 |
---|---|---|
S |
Spades | 0 |
C |
Clubs | 1 |
H |
Hearts | 2 |
D |
Diamonds | 3 |
任何标准牌组的牌都可以唯一地表示为从0到51的任何u32
。通过将suit字段值乘以13,然后加上牌的value字段。
use cardseed::{Card, Suit};
let card = Card {
suit: Suit::Clubs,
value: 4,
};
assert_eq!(u32::from(card), 17);
例如,牌"TD"
(红桃10),可以表示为整数$(3 \cdot 13) + 9 = 48$。
牌组
Deck
是一个任意数量牌的向量。Deck可以序列化和解析为序列化的Card字符串,每个Card字符串由空白字符分隔。
use cardseed::{Deck, Card, Suit};
use std::vec::Vec;
let deck = Deck {
cards: vec![
Card {
suit: Suit::Clubs,
value: 10,
},
Card {
suit: Suit::Hearts,
value: 12,
},
Card {
suit: Suit::Diamonds,
value: 1,
},
],
};
let deck_str = format!("{}", deck);
assert_eq!(deck_str, "JC KH 2D");
let parsed_deck = match deck_str.parse::<Deck>() {
Ok(deck) => deck,
Err(e) => panic!("failed to parse deck: {}", e),
};
assert_eq!(parsed_deck, deck);
依赖项
~1MB
~16K SLoC