Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix base64 #289

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions libsignal-service/src/account_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use zkgroup::profiles::ProfileKey;
use crate::pre_keys::{KyberPreKeyEntity, PreKeysStore};
use crate::proto::DeviceName;
use crate::push_service::{AvatarWrite, RecaptchaAttributes, ServiceIdType};
use crate::utils::BASE64_RELAXED;
use crate::ServiceAddress;
use crate::{
configuration::{Endpoint, ServiceCredentials},
Expand Down Expand Up @@ -297,7 +298,7 @@ impl<Service: PushService> AccountManager<Service> {
&[],
HttpAuthOverride::NoOverride,
&ProvisioningMessage {
body: BASE64_STANDARD.encode(body),
body: BASE64_RELAXED.encode(body),
},
)
.await
Expand Down Expand Up @@ -327,7 +328,7 @@ impl<Service: PushService> AccountManager<Service> {
let ephemeral_id = query.get("uuid").ok_or(LinkError::InvalidUuid)?;
let pub_key =
query.get("pub_key").ok_or(LinkError::InvalidPublicKey)?;
let pub_key = BASE64_STANDARD
let pub_key = BASE64_RELAXED
.decode(&**pub_key)
.map_err(|_e| LinkError::InvalidPublicKey)?;
let pub_key = PublicKey::deserialize(&pub_key)
Expand Down Expand Up @@ -642,7 +643,8 @@ pub fn decrypt_device_name(

#[cfg(test)]
mod tests {
use base64::prelude::*;
use crate::utils::BASE64_RELAXED;
use base64::Engine;
use libsignal_protocol::{KeyPair, PrivateKey, PublicKey};

use super::DeviceName;
Expand Down Expand Up @@ -670,21 +672,21 @@ mod tests {
#[test]
fn decrypt_device_name() -> anyhow::Result<()> {
let ephemeral_private_key = PrivateKey::deserialize(
&BASE64_STANDARD
&BASE64_RELAXED
.decode("0CgxHjwwblXjvX8sD5wZDWdYToMRf+CZSlgaUrxCGVo=")?,
)?;
let ephemeral_public_key = PublicKey::deserialize(
&BASE64_STANDARD
&BASE64_RELAXED
.decode("BcZS+Lt6yAKbEpXnRX+I5wHqesuvu93Q2V+fjidwW8R6")?,
)?;

let device_name = DeviceName {
ephemeral_public: Some(ephemeral_public_key.serialize().to_vec()),
synthetic_iv: Some(
BASE64_STANDARD.decode("86gekHGmltnnZ9QARhiFcg==")?,
BASE64_RELAXED.decode("86gekHGmltnnZ9QARhiFcg==")?,
),
ciphertext: Some(
BASE64_STANDARD
BASE64_RELAXED
.decode("MtJ9/9KBWLBVAxfZJD4pLKzP4q+iodRJeCc+/A==")?,
),
};
Expand Down
5 changes: 3 additions & 2 deletions libsignal-service/src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
envelope::Envelope,
push_service::ServiceError,
sender::OutgoingPushMessage,
utils::BASE64_RELAXED,
ServiceAddress,
};
/// Decrypts incoming messages and encrypts outgoing messages.
Expand Down Expand Up @@ -365,7 +366,7 @@ where
r#type: Type::UnidentifiedSender as u32,
destination_device_id: address.device_id().into(),
destination_registration_id,
content: BASE64_STANDARD.encode(message),
content: BASE64_RELAXED.encode(message),
})
} else {
let message = message_encrypt(
Expand All @@ -380,7 +381,7 @@ where
let destination_registration_id =
session_record.remote_registration_id()?;

let body = BASE64_STANDARD.encode(message.serialize());
let body = BASE64_RELAXED.encode(message.serialize());

use crate::proto::envelope::Type;
let message_type = match message.message_type() {
Expand Down
9 changes: 5 additions & 4 deletions libsignal-service/src/configuration.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{collections::HashMap, str::FromStr};

use crate::utils::BASE64_RELAXED;
use base64::prelude::*;
use libsignal_protocol::PublicKey;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -130,8 +131,8 @@ impl From<&SignalServers> for ServiceConfiguration {
"https://api-staging.directory.signal.org".parse().unwrap(),
certificate_authority: include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/certs/staging-root-ca.pem")).to_string(),
unidentified_sender_trust_root:
PublicKey::deserialize(&BASE64_STANDARD.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx").unwrap()).unwrap(),
zkgroup_server_public_params: bincode::deserialize(&BASE64_STANDARD.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXZSSsOZ6s7M1+rTJN0bI5CKY2PX29y5Ok3jSWufIKcgKOnWoP67d5b2du2ZVJjpjfibNIHbT/cegy/sBLoFwtHogVYUewANUAXIaMPyCLRArsKhfJ5wBtTminG/PAvuBdJ70Z/bXVPf8TVsR292zQ65xwvWTejROW6AZX6aqucUj").unwrap()).unwrap(),
PublicKey::deserialize(&BASE64_RELAXED.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx").unwrap()).unwrap(),
zkgroup_server_public_params: bincode::deserialize(&BASE64_RELAXED.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXZSSsOZ6s7M1+rTJN0bI5CKY2PX29y5Ok3jSWufIKcgKOnWoP67d5b2du2ZVJjpjfibNIHbT/cegy/sBLoFwtHogVYUewANUAXIaMPyCLRArsKhfJ5wBtTminG/PAvuBdJ70Z/bXVPf8TVsR292zQ65xwvWTejROW6AZX6aqucUj").unwrap()).unwrap(),
},
// configuration with the Signal API production endpoints
// https://github.com/signalapp/Signal-Desktop/blob/master/config/production.json
Expand All @@ -148,9 +149,9 @@ impl From<&SignalServers> for ServiceConfiguration {
contact_discovery_url: "https://api.directory.signal.org".parse().unwrap(),
certificate_authority: include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/certs/production-root-ca.pem")).to_string(),
unidentified_sender_trust_root:
PublicKey::deserialize(&BASE64_STANDARD.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF").unwrap()).unwrap(),
PublicKey::deserialize(&BASE64_RELAXED.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF").unwrap()).unwrap(),
zkgroup_server_public_params: bincode::deserialize(
&BASE64_STANDARD.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXTLfN0/vLt98KDPnxwAQL9j5V1jGOY8jQl6MLxEs56cwXN0dqCnImzVH3TZT1cJ8SW1BRX6qIVxEzjsSGx3yxF3suAilPMqGRp4ffyopjMD1JXiKR2RwLKzizUe5e8XyGOy9fplzhw3jVzTRyUZTRSZKkMLWcQ/gv0E4aONNqs4P").unwrap()).unwrap(),
&BASE64_RELAXED.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXTLfN0/vLt98KDPnxwAQL9j5V1jGOY8jQl6MLxEs56cwXN0dqCnImzVH3TZT1cJ8SW1BRX6qIVxEzjsSGx3yxF3suAilPMqGRp4ffyopjMD1JXiKR2RwLKzizUe5e8XyGOy9fplzhw3jVzTRyUZTRSZKkMLWcQ/gv0E4aONNqs4P").unwrap()).unwrap(),
},
}
}
Expand Down
3 changes: 2 additions & 1 deletion libsignal-service/src/groups_v2/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
prelude::{PushService, ServiceError},
proto::GroupContextV2,
push_service::{HttpAuth, HttpAuthOverride, ServiceIds},
utils::BASE64_RELAXED,
};

use base64::prelude::*;
Expand Down Expand Up @@ -41,7 +42,7 @@ impl CredentialResponse {
self.credentials
.into_iter()
.map(|c| {
let bytes = BASE64_STANDARD.decode(c.credential)?;
let bytes = BASE64_RELAXED.decode(c.credential)?;
let data = bincode::deserialize(&bytes)?;
Ok((c.redemption_time, data))
})
Expand Down
3 changes: 2 additions & 1 deletion libsignal-service/src/groups_v2/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
self, group_attribute_blob, GroupAttributeBlob,
Member as EncryptedMember,
},
utils::BASE64_RELAXED,
};

use super::{
Expand Down Expand Up @@ -404,7 +405,7 @@ impl GroupOperations {
let modify_invite_link_password =
actions.modify_invite_link_password.into_iter().map(|m| {
Ok(GroupChange::InviteLinkPassword(
BASE64_STANDARD.encode(m.invite_link_password),
BASE64_RELAXED.encode(m.invite_link_password),
))
});

Expand Down
5 changes: 3 additions & 2 deletions libsignal-service/src/provisioning/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{array::TryFromSliceError, borrow::Cow};

pub use cipher::ProvisioningCipher;

use base64::prelude::*;
use base64::Engine;
use derivative::Derivative;
use futures::StreamExt;
use futures::{channel::mpsc::Sender, pin_mut, SinkExt};
Expand All @@ -20,6 +20,7 @@ use zkgroup::profiles::ProfileKey;
use pipe::{ProvisioningPipe, ProvisioningStep};

use crate::prelude::ServiceError;
use crate::utils::BASE64_RELAXED;
use crate::{
account_manager::encrypt_device_name,
pre_keys::{
Expand Down Expand Up @@ -223,7 +224,7 @@ pub async fn link_device<
let pni_signed_pre_key =
generate_signed_pre_key(pni_store, csprng, &pni_key_pair).await?;

let encrypted_device_name = BASE64_STANDARD.encode(
let encrypted_device_name = BASE64_RELAXED.encode(
encrypt_device_name(csprng, device_name, &aci_public_key)?
.encode_to_vec(),
);
Expand Down
5 changes: 3 additions & 2 deletions libsignal-service/src/provisioning/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use base64::prelude::*;
use base64::Engine;
use bytes::Bytes;
use futures::{
channel::{
Expand All @@ -16,6 +16,7 @@ use crate::{
ProvisioningUuid, WebSocketRequestMessage, WebSocketResponseMessage,
},
provisioning::ProvisioningError,
utils::BASE64_RELAXED,
websocket::SignalWebSocket,
};

Expand Down Expand Up @@ -98,7 +99,7 @@ impl ProvisioningPipe {
.append_pair("uuid", &uuid.uuid.unwrap())
.append_pair(
"pub_key",
&BASE64_STANDARD.encode(
&BASE64_RELAXED.encode(
self.provisioning_cipher.public_key().serialize(),
),
);
Expand Down
42 changes: 31 additions & 11 deletions libsignal-service/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
// Signal sometimes adds padding, sometimes it does not.
// This requires a custom decoding engine.
// This engine is as general as possible.
pub const BASE64_RELAXED: base64::engine::GeneralPurpose =
base64::engine::GeneralPurpose::new(
&base64::alphabet::STANDARD,
base64::engine::GeneralPurposeConfig::new()
.with_encode_padding(true)
.with_decode_padding_mode(
base64::engine::DecodePaddingMode::Indifferent,
),
);

pub mod serde_base64 {
use super::BASE64_RELAXED;
use base64::prelude::*;
use serde::{Deserialize, Deserializer, Serializer};

Expand All @@ -7,7 +21,7 @@ pub mod serde_base64 {
T: AsRef<[u8]>,
S: Serializer,
{
serializer.serialize_str(&BASE64_STANDARD.encode(bytes.as_ref()))
serializer.serialize_str(&BASE64_RELAXED.encode(bytes.as_ref()))
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
Expand All @@ -16,14 +30,15 @@ pub mod serde_base64 {
{
use serde::de::Error;
String::deserialize(deserializer).and_then(|string| {
BASE64_STANDARD
BASE64_RELAXED
.decode(string)
.map_err(|err| Error::custom(err.to_string()))
})
}
}

pub mod serde_optional_base64 {
use super::BASE64_RELAXED;
use base64::prelude::*;
use serde::{Deserialize, Deserializer, Serializer};

Expand Down Expand Up @@ -51,7 +66,7 @@ pub mod serde_optional_base64 {
{
use serde::de::Error;
match Option::<String>::deserialize(deserializer)? {
Some(s) => BASE64_STANDARD
Some(s) => BASE64_RELAXED
.decode(s)
.map_err(|err| Error::custom(err.to_string()))
.map(Some),
Expand All @@ -61,6 +76,7 @@ pub mod serde_optional_base64 {
}

pub mod serde_public_key {
use super::BASE64_RELAXED;
use base64::prelude::*;
use libsignal_protocol::PublicKey;
use serde::{Deserialize, Deserializer, Serializer};
Expand All @@ -73,15 +89,15 @@ pub mod serde_public_key {
S: Serializer,
{
let public_key = public_key.serialize();
serializer.serialize_str(&BASE64_STANDARD.encode(&public_key))
serializer.serialize_str(&BASE64_RELAXED.encode(&public_key))
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
where
D: Deserializer<'de>,
{
PublicKey::deserialize(
&BASE64_STANDARD
&BASE64_RELAXED
.decode(String::deserialize(deserializer)?)
.map_err(serde::de::Error::custom)?,
)
Expand All @@ -90,6 +106,7 @@ pub mod serde_public_key {
}

pub mod serde_optional_public_key {
use super::BASE64_RELAXED;
use base64::prelude::*;
use libsignal_protocol::PublicKey;
use serde::{Deserialize, Deserializer, Serializer};
Expand Down Expand Up @@ -120,7 +137,7 @@ pub mod serde_optional_public_key {
match Option::<String>::deserialize(deserializer)? {
Some(public_key) => Ok(Some(
PublicKey::deserialize(
&BASE64_STANDARD
&BASE64_RELAXED
.decode(public_key)
.map_err(serde::de::Error::custom)?,
)
Expand All @@ -132,6 +149,7 @@ pub mod serde_optional_public_key {
}

pub mod serde_private_key {
use super::BASE64_RELAXED;
use base64::prelude::*;
use libsignal_protocol::PrivateKey;
use serde::{Deserialize, Deserializer, Serializer};
Expand All @@ -144,15 +162,15 @@ pub mod serde_private_key {
S: Serializer,
{
let public_key = public_key.serialize();
serializer.serialize_str(&BASE64_STANDARD.encode(public_key))
serializer.serialize_str(&BASE64_RELAXED.encode(public_key))
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<PrivateKey, D::Error>
where
D: Deserializer<'de>,
{
PrivateKey::deserialize(
&BASE64_STANDARD
&BASE64_RELAXED
.decode(String::deserialize(deserializer)?)
.map_err(serde::de::Error::custom)?,
)
Expand All @@ -161,6 +179,7 @@ pub mod serde_private_key {
}

pub mod serde_optional_private_key {
use super::BASE64_RELAXED;
use base64::prelude::*;
use libsignal_protocol::PrivateKey;
use serde::{Deserialize, Deserializer, Serializer};
Expand Down Expand Up @@ -191,7 +210,7 @@ pub mod serde_optional_private_key {
match Option::<String>::deserialize(deserializer)? {
Some(private_key) => Ok(Some(
PrivateKey::deserialize(
&BASE64_STANDARD
&BASE64_RELAXED
.decode(private_key)
.map_err(serde::de::Error::custom)?,
)
Expand All @@ -205,6 +224,7 @@ pub mod serde_optional_private_key {
pub mod serde_signaling_key {
use std::convert::TryInto;

use super::BASE64_RELAXED;
use crate::configuration::SignalingKey;
use base64::prelude::*;
use serde::{Deserialize, Deserializer, Serializer};
Expand All @@ -216,7 +236,7 @@ pub mod serde_signaling_key {
where
S: Serializer,
{
serializer.serialize_str(&BASE64_STANDARD.encode(signaling_key))
serializer.serialize_str(&BASE64_RELAXED.encode(signaling_key))
}

pub fn deserialize<'de, D>(
Expand All @@ -225,7 +245,7 @@ pub mod serde_signaling_key {
where
D: Deserializer<'de>,
{
BASE64_STANDARD
BASE64_RELAXED
.decode(String::deserialize(deserializer)?)
.map_err(serde::de::Error::custom)?
.try_into()
Expand Down
5 changes: 3 additions & 2 deletions libsignal-service/src/websocket/sender.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
sender::{OutgoingPushMessages, SendMessageResponse},
unidentified_access::UnidentifiedAccess,
utils::BASE64_RELAXED,
};
use base64::prelude::*;

use super::*;
use base64::Engine;

impl SignalWebSocket {
pub async fn send_messages(
Expand All @@ -23,7 +24,7 @@ impl SignalWebSocket {
let path = format!("/v1/messages/{}", messages.recipient.uuid);
let header = format!(
"Unidentified-Access-Key:{}",
BASE64_STANDARD.encode(&access.key)
BASE64_RELAXED.encode(&access.key)
);
self.put_json_with_headers(&path, messages, vec![header])
.await
Expand Down
Loading