Skip to content

Commit

Permalink
Exchange sodiumoxide with maintained alternatives
Browse files Browse the repository at this point in the history
  • Loading branch information
threema-donat committed Feb 5, 2024
1 parent ce8546a commit 1ab85df
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 161 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ Possible log types:

### Unreleased

- [added] Re-export `crypto_secretbox::Nonce`
- [changed] Replace `sodiumoxide` with `crypto_box` and `crypto_secretbox`
- [changed] Replace re-exports of `PublicKey`, `SecretKey` and `Key`
- [changed] Replace `&[u8; 24]` with `crypto_secretbox::Nonce`
- [changed] Return result in `encrypt_*` functions
- [changed] Use `hmac` and `sha2` crates for calculating MAC
- [changed] Set rust version to 1.75.0

### v0.16.0 (2023-09-04)

- [added] Expose encryption functions: `encrypt` and `encrypt_raw` (#59)
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ reqwest = { version = "0.11", features = ["rustls-tls-native-roots", "multipart"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_urlencoded = { version = "0.7", optional = true }
sodiumoxide = "0.2.0"
hmac = "0.12.1"
sha2 = "0.10.8"
crypto_secretbox = "0.1.1"
crypto_box = "0.9.1"
rand = "0.8.5"

[dev-dependencies]
docopt = "1.1.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/download_blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async fn main() {
let bytes = HEXLOWER_PERMISSIVE
.decode(blob_key_raw.as_bytes())
.expect("Invalid blob key");
Some(Key::from_slice(&bytes).expect("Invalid blob key bytes"))
Some(Key::clone_from_slice(bytes.as_ref()))
} else {
None
};
Expand Down
9 changes: 5 additions & 4 deletions examples/generate_keypair.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crypto_secretbox::aead::OsRng;
use data_encoding::HEXLOWER;
use sodiumoxide::crypto::box_;

fn main() {
println!("Generating new random nacl/libsodium crypto box keypair:\n");
let (pk, sk) = box_::gen_keypair();
println!(" Public: {}", HEXLOWER.encode(&pk.0));
println!(" Private: {}", HEXLOWER.encode(&sk.0));
let sk = crypto_box::SecretKey::generate(&mut OsRng);
let pk = sk.public_key();
println!(" Public: {}", HEXLOWER.encode(pk.as_bytes()));
println!(" Private: {}", HEXLOWER.encode(&sk.to_bytes()));
println!("\nKeep the private key safe, and don't share it with anybody!");
}
16 changes: 9 additions & 7 deletions examples/receive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@ async fn main() {
// Command line arguments
let our_id = args.get_str("<our-id>");
let secret = args.get_str("<secret>");
let private_key = HEXLOWER_PERMISSIVE
let key_bytes = HEXLOWER_PERMISSIVE
.decode(args.get_str("<private-key>").as_bytes())
.ok()
.and_then(|bytes| SecretKey::from_slice(&bytes))
.unwrap_or_else(|| {
eprintln!("Invalid private key");
.unwrap_or_else(|_| {
eprintln!("No private key provided");
std::process::exit(1);
});
let private_key = SecretKey::from_slice(&key_bytes).unwrap_or_else(|_| {
eprintln!("Invalid private key");
std::process::exit(1);
});
let request_body = args.get_str("<request-body>");

// Create E2eApi instance
let api = ApiBuilder::new(our_id, secret)
.with_private_key_bytes(private_key.as_ref())
.and_then(|builder| builder.into_e2e())
.with_private_key(private_key)
.into_e2e()
.unwrap();

// Parse request body
Expand Down
7 changes: 5 additions & 2 deletions examples/send_e2e_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ async fn main() {
file: file_bytes,
thumbnail: thumbnail_bytes,
};
let (encrypted, key) = encrypt_file_data(&file_data);
let (encrypted, key) = etry!(encrypt_file_data(&file_data), "Could not encrypt file");

// Upload files to blob server
let file_blob_id = etry!(
Expand Down Expand Up @@ -126,7 +126,10 @@ async fn main() {
.rendering_type(rendering_type)
.build()
.expect("Could not build FileMessage");
let encrypted = api.encrypt_file_msg(&msg, &public_key.into());
let encrypted = etry!(
api.encrypt_file_msg(&msg, &public_key.into()),
"Could not encrypt file msg"
);

// Send
let msg_id = api.send(to, &encrypted, false).await;
Expand Down
24 changes: 17 additions & 7 deletions examples/send_e2e_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ async fn main() {
println!("Could not read file: {}", e);
process::exit(1);
});
let encrypted_image = api.encrypt_raw(&img_data, &recipient_key);
let encrypted_image = api
.encrypt_raw(&img_data, &recipient_key)
.unwrap_or_else(|_| {
println!("Could encrypt raw msg");
process::exit(1);
});

// Upload image to blob server
let blob_id = api
Expand All @@ -73,12 +78,17 @@ async fn main() {
});

// Create image message
let msg = api.encrypt_image_msg(
&blob_id,
img_data.len() as u32,
&encrypted_image.nonce,
&recipient_key,
);
let msg = api
.encrypt_image_msg(
&blob_id,
img_data.len() as u32,
&encrypted_image.nonce,
&recipient_key,
)
.unwrap_or_else(|_| {
println!("Could not encrypt image msg");
process::exit(1);
});

// Send
let msg_id = api.send(to, &msg, false).await;
Expand Down
7 changes: 6 additions & 1 deletion examples/send_e2e_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ async fn main() {
});

// Encrypt and send
let encrypted = api.encrypt_text_msg(&text, &public_key.into());
let encrypted = api
.encrypt_text_msg(&text, &public_key.into())
.unwrap_or_else(|_| {
println!("Could not encrypt text msg");
process::exit(1);
});
let msg_id = api.send(to, &encrypted, false).await;

match msg_id {
Expand Down
27 changes: 18 additions & 9 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use std::{
time::Duration,
};

use crypto_box::{PublicKey, SecretKey};
use crypto_secretbox::Nonce;
use data_encoding::HEXLOWER_PERMISSIVE;
use reqwest::Client;
use sodiumoxide::crypto::box_::PublicKey;

use crate::{
connection::{blob_download, blob_upload, send_e2e, send_simple, Recipient},
Expand All @@ -20,7 +21,7 @@ use crate::{
},
receive::IncomingMessage,
types::{BlobId, FileMessage, MessageType},
SecretKey, MSGAPI_URL,
MSGAPI_URL,
};

fn make_reqwest_client() -> Client {
Expand Down Expand Up @@ -173,7 +174,11 @@ impl E2eApi {
}

/// Encrypt a text message for the specified recipient public key.
pub fn encrypt_text_msg(&self, text: &str, recipient_key: &RecipientKey) -> EncryptedMessage {
pub fn encrypt_text_msg(
&self,
text: &str,
recipient_key: &RecipientKey,
) -> Result<EncryptedMessage, CryptoError> {
let data = text.as_bytes();
let msgtype = MessageType::Text;
encrypt(data, msgtype, &recipient_key.0, &self.private_key)
Expand All @@ -192,9 +197,9 @@ impl E2eApi {
&self,
blob_id: &BlobId,
img_size_bytes: u32,
image_data_nonce: &[u8; 24],
image_data_nonce: &Nonce,
recipient_key: &RecipientKey,
) -> EncryptedMessage {
) -> Result<EncryptedMessage, CryptoError> {
encrypt_image_msg(
blob_id,
img_size_bytes,
Expand All @@ -214,7 +219,7 @@ impl E2eApi {
&self,
msg: &FileMessage,
recipient_key: &RecipientKey,
) -> EncryptedMessage {
) -> Result<EncryptedMessage, CryptoError> {
encrypt_file_msg(msg, &recipient_key.0, &self.private_key)
}

Expand All @@ -233,12 +238,16 @@ impl E2eApi {
raw_data: &[u8],
msgtype: MessageType,
recipient_key: &RecipientKey,
) -> EncryptedMessage {
) -> Result<EncryptedMessage, CryptoError> {
encrypt(raw_data, msgtype, &recipient_key.0, &self.private_key)
}

/// Encrypt raw bytes for the specified recipient public key.
pub fn encrypt_raw(&self, raw_data: &[u8], recipient_key: &RecipientKey) -> EncryptedMessage {
pub fn encrypt_raw(
&self,
raw_data: &[u8],
recipient_key: &RecipientKey,
) -> Result<EncryptedMessage, CryptoError> {
encrypt_raw(raw_data, &recipient_key.0, &self.private_key)
}

Expand Down Expand Up @@ -508,7 +517,7 @@ impl ApiBuilder {
/// Set the private key from a byte slice. Only needed for E2e mode.
pub fn with_private_key_bytes(mut self, private_key: &[u8]) -> Result<Self, ApiBuilderError> {
let private_key = SecretKey::from_slice(private_key)
.ok_or_else(|| ApiBuilderError::InvalidKey("Invalid libsodium private key".into()))?;
.map_err(|_| ApiBuilderError::InvalidKey("Invalid libsodium private key".into()))?;
self.private_key = Some(private_key);
Ok(self)
}
Expand Down
Loading

0 comments on commit 1ab85df

Please sign in to comment.