Skip to content

Commit

Permalink
Merge pull request #289 from Schmiddiii/base64
Browse files Browse the repository at this point in the history
Fix base64
  • Loading branch information
rubdos authored Jan 30, 2024
2 parents 99663a3 + 5b95d5f commit a2e7540
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 32 deletions.
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

0 comments on commit a2e7540

Please sign in to comment.