pub struct PrekeyServer<K> { /* private fields */ }Expand description
In-memory store of users’ prekeys, keyed by any user id type K
Implementations§
Source§impl<K: Eq + Hash> PrekeyServer<K>
impl<K: Eq + Hash> PrekeyServer<K>
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty server
Examples found in repository?
examples/prekey_server.rs (line 17)
16fn main() {
17 let mut server = PrekeyServer::new();
18
19 // --- Bob's device: create prekeys, keep the secrets, publish the signed public parts
20 let mut bob_signer = SignerPair::create();
21 let bob_last_resort = KEMPair::create();
22 let bob_last_resort_signed = SignedPrekey::new(&mut bob_signer, &bob_last_resort).unwrap();
23
24 let mut bob_one_time: HashMap<PrekeyId, KEMPair> = HashMap::new();
25 let mut published = Vec::new();
26 for _ in 0..3 {
27 let prekey = KEMPair::create();
28 let signed = SignedPrekey::new(&mut bob_signer, &prekey).unwrap();
29 bob_one_time.insert(signed.id(), prekey);
30 published.push(signed);
31 }
32 server
33 .publish(
34 "bob",
35 *bob_signer.pub_key_bytes(),
36 bob_last_resort_signed.clone(),
37 published,
38 )
39 .unwrap();
40 println!(
41 "Bob published 3 one-time prekeys and a last-resort prekey ({} one-time left)",
42 server.one_time_remaining(&"bob")
43 );
44
45 // --- Alice's device: fetch Bob's bundle and start a session
46 let alice_signer = SignerPair::create();
47 let bundle = server.fetch(&"bob").unwrap();
48
49 // In a real app Alice checks Bob's identity key against a copy she trusts
50 // (for example by comparing safety numbers in person)
51 assert_eq!(&bundle.identity, bob_signer.pub_key_bytes());
52
53 let base_nonce = create_nonce(&gen_session_id(), 0);
54 let (mut alice_session, ciphertext) = MessageSession::new_initiator(
55 alice_signer.clone(),
56 base_nonce,
57 &bundle.prekey,
58 &bundle.identity,
59 )
60 .unwrap();
61
62 // Alice sends Bob: the ciphertext, the prekey id, the base nonce and her identity key
63 let prekey_id = bundle.prekey.id();
64
65 // --- Bob's device: find the prekey Alice used and set up his side
66 let mut bob_session = if let Some(prekey) = bob_one_time.remove(&prekey_id) {
67 // One-time prekey: it is removed from Bob's store above and wiped when dropped
68 // at the end of this block, which gives the session forward secrecy
69 MessageSession::new_responder(
70 &prekey,
71 bob_signer.clone(),
72 base_nonce,
73 &ciphertext,
74 alice_signer.pub_key_bytes(),
75 )
76 .unwrap()
77 } else if prekey_id == bob_last_resort_signed.id() {
78 // Last-resort prekey: kept until Bob rotates it
79 MessageSession::new_responder(
80 &bob_last_resort,
81 bob_signer.clone(),
82 base_nonce,
83 &ciphertext,
84 alice_signer.pub_key_bytes(),
85 )
86 .unwrap()
87 } else {
88 panic!("unknown prekey");
89 };
90 println!(
91 "Session set up; Bob has {} one-time prekey secrets left on his device",
92 bob_one_time.len()
93 );
94
95 // --- Talk
96 let encrypted = alice_session.craft_message(b"Hi Bob!").unwrap();
97 let message = bob_session.validate_message(&encrypted).unwrap();
98 println!("Bob received: {}", String::from_utf8_lossy(&message));
99
100 let encrypted = bob_session.craft_message(b"Hi Alice!").unwrap();
101 let reply = alice_session.validate_message(&encrypted).unwrap();
102 println!("Alice received: {}", String::from_utf8_lossy(&reply));
103}Sourcepub fn publish(
&mut self,
user: K,
identity: PublicKeyBytes,
last_resort: SignedPrekey,
one_time: Vec<SignedPrekey>,
) -> Result<(), CryptoError>
pub fn publish( &mut self, user: K, identity: PublicKeyBytes, last_resort: SignedPrekey, one_time: Vec<SignedPrekey>, ) -> Result<(), CryptoError>
Publishes a user’s prekeys
The first call for a user registers identity. Later calls must use the same
identity; they add the new one-time prekeys and replace the last-resort prekey.
Each one-time prekey should only be published once.
§Arguments
user- The user’s ididentity- The user’s FN-DSA identity public keylast_resort- The user’s current last-resort prekeyone_time- New one-time prekeys
§Returns
Result<(), CryptoError>:InvalidSignatureif any prekey is not signed byidentity, orInvalidKeyif the user is registered with another identity. Nothing is stored on error.
Examples found in repository?
examples/prekey_server.rs (lines 33-38)
16fn main() {
17 let mut server = PrekeyServer::new();
18
19 // --- Bob's device: create prekeys, keep the secrets, publish the signed public parts
20 let mut bob_signer = SignerPair::create();
21 let bob_last_resort = KEMPair::create();
22 let bob_last_resort_signed = SignedPrekey::new(&mut bob_signer, &bob_last_resort).unwrap();
23
24 let mut bob_one_time: HashMap<PrekeyId, KEMPair> = HashMap::new();
25 let mut published = Vec::new();
26 for _ in 0..3 {
27 let prekey = KEMPair::create();
28 let signed = SignedPrekey::new(&mut bob_signer, &prekey).unwrap();
29 bob_one_time.insert(signed.id(), prekey);
30 published.push(signed);
31 }
32 server
33 .publish(
34 "bob",
35 *bob_signer.pub_key_bytes(),
36 bob_last_resort_signed.clone(),
37 published,
38 )
39 .unwrap();
40 println!(
41 "Bob published 3 one-time prekeys and a last-resort prekey ({} one-time left)",
42 server.one_time_remaining(&"bob")
43 );
44
45 // --- Alice's device: fetch Bob's bundle and start a session
46 let alice_signer = SignerPair::create();
47 let bundle = server.fetch(&"bob").unwrap();
48
49 // In a real app Alice checks Bob's identity key against a copy she trusts
50 // (for example by comparing safety numbers in person)
51 assert_eq!(&bundle.identity, bob_signer.pub_key_bytes());
52
53 let base_nonce = create_nonce(&gen_session_id(), 0);
54 let (mut alice_session, ciphertext) = MessageSession::new_initiator(
55 alice_signer.clone(),
56 base_nonce,
57 &bundle.prekey,
58 &bundle.identity,
59 )
60 .unwrap();
61
62 // Alice sends Bob: the ciphertext, the prekey id, the base nonce and her identity key
63 let prekey_id = bundle.prekey.id();
64
65 // --- Bob's device: find the prekey Alice used and set up his side
66 let mut bob_session = if let Some(prekey) = bob_one_time.remove(&prekey_id) {
67 // One-time prekey: it is removed from Bob's store above and wiped when dropped
68 // at the end of this block, which gives the session forward secrecy
69 MessageSession::new_responder(
70 &prekey,
71 bob_signer.clone(),
72 base_nonce,
73 &ciphertext,
74 alice_signer.pub_key_bytes(),
75 )
76 .unwrap()
77 } else if prekey_id == bob_last_resort_signed.id() {
78 // Last-resort prekey: kept until Bob rotates it
79 MessageSession::new_responder(
80 &bob_last_resort,
81 bob_signer.clone(),
82 base_nonce,
83 &ciphertext,
84 alice_signer.pub_key_bytes(),
85 )
86 .unwrap()
87 } else {
88 panic!("unknown prekey");
89 };
90 println!(
91 "Session set up; Bob has {} one-time prekey secrets left on his device",
92 bob_one_time.len()
93 );
94
95 // --- Talk
96 let encrypted = alice_session.craft_message(b"Hi Bob!").unwrap();
97 let message = bob_session.validate_message(&encrypted).unwrap();
98 println!("Bob received: {}", String::from_utf8_lossy(&message));
99
100 let encrypted = bob_session.craft_message(b"Hi Alice!").unwrap();
101 let reply = alice_session.validate_message(&encrypted).unwrap();
102 println!("Alice received: {}", String::from_utf8_lossy(&reply));
103}Sourcepub fn fetch(&mut self, user: &K) -> Option<PrekeyBundle>
pub fn fetch(&mut self, user: &K) -> Option<PrekeyBundle>
Hands out a prekey bundle for starting a session with user
A one-time prekey is removed from the server as it is handed out.
§Returns
The bundle, or None if the user is unknown
Examples found in repository?
examples/prekey_server.rs (line 47)
16fn main() {
17 let mut server = PrekeyServer::new();
18
19 // --- Bob's device: create prekeys, keep the secrets, publish the signed public parts
20 let mut bob_signer = SignerPair::create();
21 let bob_last_resort = KEMPair::create();
22 let bob_last_resort_signed = SignedPrekey::new(&mut bob_signer, &bob_last_resort).unwrap();
23
24 let mut bob_one_time: HashMap<PrekeyId, KEMPair> = HashMap::new();
25 let mut published = Vec::new();
26 for _ in 0..3 {
27 let prekey = KEMPair::create();
28 let signed = SignedPrekey::new(&mut bob_signer, &prekey).unwrap();
29 bob_one_time.insert(signed.id(), prekey);
30 published.push(signed);
31 }
32 server
33 .publish(
34 "bob",
35 *bob_signer.pub_key_bytes(),
36 bob_last_resort_signed.clone(),
37 published,
38 )
39 .unwrap();
40 println!(
41 "Bob published 3 one-time prekeys and a last-resort prekey ({} one-time left)",
42 server.one_time_remaining(&"bob")
43 );
44
45 // --- Alice's device: fetch Bob's bundle and start a session
46 let alice_signer = SignerPair::create();
47 let bundle = server.fetch(&"bob").unwrap();
48
49 // In a real app Alice checks Bob's identity key against a copy she trusts
50 // (for example by comparing safety numbers in person)
51 assert_eq!(&bundle.identity, bob_signer.pub_key_bytes());
52
53 let base_nonce = create_nonce(&gen_session_id(), 0);
54 let (mut alice_session, ciphertext) = MessageSession::new_initiator(
55 alice_signer.clone(),
56 base_nonce,
57 &bundle.prekey,
58 &bundle.identity,
59 )
60 .unwrap();
61
62 // Alice sends Bob: the ciphertext, the prekey id, the base nonce and her identity key
63 let prekey_id = bundle.prekey.id();
64
65 // --- Bob's device: find the prekey Alice used and set up his side
66 let mut bob_session = if let Some(prekey) = bob_one_time.remove(&prekey_id) {
67 // One-time prekey: it is removed from Bob's store above and wiped when dropped
68 // at the end of this block, which gives the session forward secrecy
69 MessageSession::new_responder(
70 &prekey,
71 bob_signer.clone(),
72 base_nonce,
73 &ciphertext,
74 alice_signer.pub_key_bytes(),
75 )
76 .unwrap()
77 } else if prekey_id == bob_last_resort_signed.id() {
78 // Last-resort prekey: kept until Bob rotates it
79 MessageSession::new_responder(
80 &bob_last_resort,
81 bob_signer.clone(),
82 base_nonce,
83 &ciphertext,
84 alice_signer.pub_key_bytes(),
85 )
86 .unwrap()
87 } else {
88 panic!("unknown prekey");
89 };
90 println!(
91 "Session set up; Bob has {} one-time prekey secrets left on his device",
92 bob_one_time.len()
93 );
94
95 // --- Talk
96 let encrypted = alice_session.craft_message(b"Hi Bob!").unwrap();
97 let message = bob_session.validate_message(&encrypted).unwrap();
98 println!("Bob received: {}", String::from_utf8_lossy(&message));
99
100 let encrypted = bob_session.craft_message(b"Hi Alice!").unwrap();
101 let reply = alice_session.validate_message(&encrypted).unwrap();
102 println!("Alice received: {}", String::from_utf8_lossy(&reply));
103}Sourcepub fn one_time_remaining(&self, user: &K) -> usize
pub fn one_time_remaining(&self, user: &K) -> usize
Number of one-time prekeys left for user, so their client knows when to publish more
Examples found in repository?
examples/prekey_server.rs (line 42)
16fn main() {
17 let mut server = PrekeyServer::new();
18
19 // --- Bob's device: create prekeys, keep the secrets, publish the signed public parts
20 let mut bob_signer = SignerPair::create();
21 let bob_last_resort = KEMPair::create();
22 let bob_last_resort_signed = SignedPrekey::new(&mut bob_signer, &bob_last_resort).unwrap();
23
24 let mut bob_one_time: HashMap<PrekeyId, KEMPair> = HashMap::new();
25 let mut published = Vec::new();
26 for _ in 0..3 {
27 let prekey = KEMPair::create();
28 let signed = SignedPrekey::new(&mut bob_signer, &prekey).unwrap();
29 bob_one_time.insert(signed.id(), prekey);
30 published.push(signed);
31 }
32 server
33 .publish(
34 "bob",
35 *bob_signer.pub_key_bytes(),
36 bob_last_resort_signed.clone(),
37 published,
38 )
39 .unwrap();
40 println!(
41 "Bob published 3 one-time prekeys and a last-resort prekey ({} one-time left)",
42 server.one_time_remaining(&"bob")
43 );
44
45 // --- Alice's device: fetch Bob's bundle and start a session
46 let alice_signer = SignerPair::create();
47 let bundle = server.fetch(&"bob").unwrap();
48
49 // In a real app Alice checks Bob's identity key against a copy she trusts
50 // (for example by comparing safety numbers in person)
51 assert_eq!(&bundle.identity, bob_signer.pub_key_bytes());
52
53 let base_nonce = create_nonce(&gen_session_id(), 0);
54 let (mut alice_session, ciphertext) = MessageSession::new_initiator(
55 alice_signer.clone(),
56 base_nonce,
57 &bundle.prekey,
58 &bundle.identity,
59 )
60 .unwrap();
61
62 // Alice sends Bob: the ciphertext, the prekey id, the base nonce and her identity key
63 let prekey_id = bundle.prekey.id();
64
65 // --- Bob's device: find the prekey Alice used and set up his side
66 let mut bob_session = if let Some(prekey) = bob_one_time.remove(&prekey_id) {
67 // One-time prekey: it is removed from Bob's store above and wiped when dropped
68 // at the end of this block, which gives the session forward secrecy
69 MessageSession::new_responder(
70 &prekey,
71 bob_signer.clone(),
72 base_nonce,
73 &ciphertext,
74 alice_signer.pub_key_bytes(),
75 )
76 .unwrap()
77 } else if prekey_id == bob_last_resort_signed.id() {
78 // Last-resort prekey: kept until Bob rotates it
79 MessageSession::new_responder(
80 &bob_last_resort,
81 bob_signer.clone(),
82 base_nonce,
83 &ciphertext,
84 alice_signer.pub_key_bytes(),
85 )
86 .unwrap()
87 } else {
88 panic!("unknown prekey");
89 };
90 println!(
91 "Session set up; Bob has {} one-time prekey secrets left on his device",
92 bob_one_time.len()
93 );
94
95 // --- Talk
96 let encrypted = alice_session.craft_message(b"Hi Bob!").unwrap();
97 let message = bob_session.validate_message(&encrypted).unwrap();
98 println!("Bob received: {}", String::from_utf8_lossy(&message));
99
100 let encrypted = bob_session.craft_message(b"Hi Alice!").unwrap();
101 let reply = alice_session.validate_message(&encrypted).unwrap();
102 println!("Alice received: {}", String::from_utf8_lossy(&reply));
103}Trait Implementations§
Auto Trait Implementations§
impl<K> Freeze for PrekeyServer<K>
impl<K> RefUnwindSafe for PrekeyServer<K>where
HashMap<K, Account>: RefUnwindSafe,
impl<K> Send for PrekeyServer<K>
impl<K> Sync for PrekeyServer<K>
impl<K> Unpin for PrekeyServer<K>
impl<K> UnsafeUnpin for PrekeyServer<K>where
HashMap<K, Account>: UnsafeUnpin,
impl<K> UnwindSafe for PrekeyServer<K>where
HashMap<K, Account>: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more