1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::secure_stream::crypto::ciphertext::CipherText;
use crate::secure_stream::crypto::error::{DecryptionError, EncryptionError};
use crate::secure_stream::serialize::{deserialize, serialize};
use serde::de::DeserializeOwned;
use serde::Serialize;
use sodiumoxide::crypto::box_;
use std::sync::Arc;
/// Precomputed shared secret key.
///
/// Can be created from a pair of our secret key and the recipient's public key.
/// As a result, we'll get the same key as the recipient with their secret key and
/// our public key.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct SharedSecretKey {
pub(super) precomputed: Arc<box_::PrecomputedKey>,
}
impl SharedSecretKey {
/// Construct shared secret key from bytes. Useful when it was serialized before.
pub fn from_bytes(key: [u8; box_::PRECOMPUTEDKEYBYTES]) -> Self {
Self {
precomputed: Arc::new(box_::PrecomputedKey(key)),
}
}
/// Convert the `SharedSecretKey` into the raw underlying bytes.
/// For anyone who wants to store the shared secret key.
pub fn into_bytes(self) -> [u8; box_::PRECOMPUTEDKEYBYTES] {
self.precomputed.0
}
/// Encrypts bytestring `plaintext` using authenticated encryption.
///
/// With authenticated encryption the recipient will be able to verify the authenticity
/// of the sender using a sender's public key.
/// If you want to use anonymous encryption, use the functions provided by `PublicKeys`
/// and `SecretKeys`.
///
/// Returns ciphertext in case of success.
/// Can return an `Error` in case of a serialisation error.
pub fn encrypt_bytes(&self, plaintext: &[u8]) -> Result<Vec<u8>, EncryptionError> {
let nonce = box_::gen_nonce();
let ciphertext = box_::seal_precomputed(plaintext, &nonce, &self.precomputed);
Ok(serialize(&CipherText {
nonce: nonce.0,
ciphertext,
})?)
}
/// Encrypts serialisable `plaintext` using authenticated encryption.
///
/// With authenticated encryption the recipient will be able to verify the authenticity
/// of the sender using a sender's public key.
/// If you wish to encrypt bytestring plaintext, use `encrypt_bytes`.
/// If you want to use anonymous encryption, use the functions provided by `PublicKeys`
/// and `SecretKeys`.
///
/// Returns ciphertext in case of success.
/// Can return an `Error` in case of a serialisation error.
pub fn encrypt<T>(&self, plaintext: &T) -> Result<Vec<u8>, EncryptionError>
where
T: Serialize,
{
self.encrypt_bytes(&serialize(plaintext)?)
}
/// Decrypts bytestring `encoded` encrypted using authenticated encryption.
///
/// With authenticated encryption we will be able to verify the authenticity
/// of the sender using a sender's public key.
///
/// Returns plaintext in case of success.
/// Can return `Error` in case of a deserialisation error, if the ciphertext
/// is not valid, or if it can not be decrypted.
pub fn decrypt_bytes(&self, encoded: &[u8]) -> Result<Vec<u8>, DecryptionError> {
let CipherText { nonce, ciphertext } = deserialize(encoded)?;
box_::open_precomputed(&ciphertext, &box_::Nonce(nonce), &self.precomputed)
.map_err(DecryptionError::GenericDecryptionError)
}
/// Decrypts serialized `ciphertext` encrypted using authenticated encryption.
///
/// With authenticated encryption we will be able to verify the authenticity
/// of the sender using a sender's public key.
///
/// Returns deserialized type `T` in case of success.
/// Can return `Error` in case of a deserialisation error, if the ciphertext
/// is not valid, or if it can not be decrypted.
pub fn decrypt<T>(&self, ciphertext: &[u8]) -> Result<T, DecryptionError>
where
T: Serialize + DeserializeOwned,
{
Ok(deserialize(&self.decrypt_bytes(ciphertext)?)?)
}
}