Upgrade base64 to 0.20

This commit is contained in:
Jonas Platte 2022-12-12 09:21:29 +01:00 committed by Jonas Platte
parent e4678284ca
commit 536341ca7e
5 changed files with 53 additions and 58 deletions

View File

@ -7,7 +7,7 @@ resolver = "2"
[workspace.dependencies]
assert_matches = "1.5.0"
assign = "1.1.1"
base64 = "0.13.1"
base64 = "0.20.0"
criterion = "0.4.0"
http = "0.2.8"
js_int = "0.2.2"

View File

@ -2,6 +2,7 @@
use std::{fmt, marker::PhantomData};
use base64::engine::fast_portable::{self, FastPortable, FastPortableConfig};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
/// A wrapper around `B` (usually `Vec<u8>`) that (de)serializes from / to a base64 string.
@ -25,7 +26,7 @@ pub trait Base64Config {
}
#[doc(hidden)]
pub struct Conf(base64::Config);
pub struct Conf(base64::alphabet::Alphabet);
/// Standard base64 character set without padding.
///
@ -36,8 +37,7 @@ pub struct Conf(base64::Config);
pub struct Standard;
impl Base64Config for Standard {
// See https://github.com/matrix-org/matrix-spec/issues/838
const CONF: Conf = Conf(base64::STANDARD_NO_PAD.decode_allow_trailing_bits(true));
const CONF: Conf = Conf(base64::alphabet::STANDARD);
}
/// Url-safe base64 character set without padding.
@ -49,7 +49,13 @@ impl Base64Config for Standard {
pub struct UrlSafe;
impl Base64Config for UrlSafe {
const CONF: Conf = Conf(base64::URL_SAFE_NO_PAD.decode_allow_trailing_bits(true));
const CONF: Conf = Conf(base64::alphabet::URL_SAFE);
}
impl<C: Base64Config, B> Base64<C, B> {
// See https://github.com/matrix-org/matrix-spec/issues/838
const CONFIG: FastPortableConfig = fast_portable::NO_PAD.with_decode_allow_trailing_bits(true);
const ENGINE: FastPortable = FastPortable::from(&C::CONF.0, Self::CONFIG);
}
impl<C: Base64Config, B: AsRef<[u8]>> Base64<C, B> {
@ -65,7 +71,7 @@ impl<C: Base64Config, B: AsRef<[u8]>> Base64<C, B> {
/// Encode the bytes contained in this `Base64` instance to unpadded base64.
pub fn encode(&self) -> String {
base64::encode_config(&self.bytes, C::CONF.0)
base64::encode_engine(self.as_bytes(), &Self::ENGINE)
}
}
@ -84,7 +90,7 @@ impl<C: Base64Config> Base64<C> {
/// Parse some base64-encoded data to create a `Base64` instance.
pub fn parse(encoded: impl AsRef<[u8]>) -> Result<Self, Base64DecodeError> {
base64::decode_config(encoded, C::CONF.0).map(Self::new).map_err(Base64DecodeError)
base64::decode_engine(encoded, &Self::ENGINE).map(Self::new).map_err(Base64DecodeError)
}
}

View File

@ -6,7 +6,7 @@ use std::{
mem,
};
use base64::{encode_config, STANDARD_NO_PAD, URL_SAFE_NO_PAD};
use base64::{alphabet, encode_engine};
use ruma_common::{
canonical_json::{redact, JsonType},
serde::{base64::Standard, Base64},
@ -55,16 +55,18 @@ static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "uns
/// A homeserver signs JSON with a key pair:
///
/// ```rust
/// # use ruma_common::serde::base64::Base64;
/// #
/// const PKCS8: &str = "\
/// MFECAQEwBQYDK2VwBCIEINjozvdfbsGEt6DD+7Uf4PiJ/YvTNXV2mIPc/\
/// tA0T+6tgSEA3TPraTczVkDPTRaX4K+AfUuyx7Mzq1UafTXypnl0t2k=\
/// tA0T+6tgSEA3TPraTczVkDPTRaX4K+AfUuyx7Mzq1UafTXypnl0t2k\
/// ";
///
/// let document = base64::decode_config(&PKCS8, base64::STANDARD_NO_PAD).unwrap();
/// let document: Base64 = Base64::parse(PKCS8).unwrap();
///
/// // Create an Ed25519 key pair.
/// let key_pair = ruma_signatures::Ed25519KeyPair::from_der(
/// &document,
/// document.as_bytes(),
/// "1".into(), // The "version" of the key.
/// )
/// .unwrap();
@ -331,14 +333,17 @@ pub fn reference_hash(
let hash = Sha256::digest(json.as_bytes());
Ok(encode_config(
hash,
match version {
RoomVersionId::V1 | RoomVersionId::V2 | RoomVersionId::V3 => STANDARD_NO_PAD,
let base64_alphabet = match version {
RoomVersionId::V1 | RoomVersionId::V2 | RoomVersionId::V3 => alphabet::STANDARD,
// Room versions higher than version 3 are url safe base64 encoded
_ => URL_SAFE_NO_PAD,
},
))
_ => alphabet::URL_SAFE,
};
let base64_engine = base64::engine::fast_portable::FastPortable::from(
&base64_alphabet,
base64::engine::fast_portable::NO_PAD,
);
Ok(encode_engine(hash, &base64_engine))
}
/// Hashes and signs an event and adds the hash and signature to objects under the keys `hashes` and
@ -366,19 +371,19 @@ pub fn reference_hash(
/// # Examples
///
/// ```rust
/// # use ruma_common::RoomVersionId;
/// # use ruma_common::{RoomVersionId, serde::base64::Base64};
/// # use ruma_signatures::{hash_and_sign_event, Ed25519KeyPair};
/// #
/// const PKCS8: &str = "\
/// MFECAQEwBQYDK2VwBCIEINjozvdfbsGEt6DD+7Uf4PiJ/YvTNXV2mIPc/\
/// tA0T+6tgSEA3TPraTczVkDPTRaX4K+AfUuyx7Mzq1UafTXypnl0t2k=\
/// tA0T+6tgSEA3TPraTczVkDPTRaX4K+AfUuyx7Mzq1UafTXypnl0t2k\
/// ";
///
/// let document = base64::decode_config(&PKCS8, base64::STANDARD_NO_PAD).unwrap();
/// let document: Base64 = Base64::parse(PKCS8).unwrap();
///
/// // Create an Ed25519 key pair.
/// let key_pair = Ed25519KeyPair::from_der(
/// &document,
/// document.as_bytes(),
/// "1".into(), // The "version" of the key.
/// )
/// .unwrap();

View File

@ -103,29 +103,29 @@ fn split_id(id: &str) -> Result<(Algorithm, String), Error> {
mod tests {
use std::collections::BTreeMap;
use base64::{decode_config, STANDARD_NO_PAD};
use pkcs8::{der::Decode, PrivateKeyInfo};
use ruma_common::{serde::Base64, RoomVersionId};
use ruma_common::{
serde::{base64::Standard, Base64},
RoomVersionId,
};
use serde_json::{from_str as from_json_str, to_string as to_json_string};
use super::{
canonical_json, hash_and_sign_event, sign_json, verify_event, verify_json, Ed25519KeyPair,
};
const PKCS8: &str = "\
fn pkcs8() -> Vec<u8> {
const ENCODED: &str = "\
MFECAQEwBQYDK2VwBCIEINjozvdfbsGEt6DD+7Uf4PiJ/YvTNXV2mIPc/\
tA0T+6tgSEA3TPraTczVkDPTRaX4K+AfUuyx7Mzq1UafTXypnl0t2k=\
tA0T+6tgSEA3TPraTczVkDPTRaX4K+AfUuyx7Mzq1UafTXypnl0t2k\
";
Base64::<Standard>::parse(ENCODED).unwrap().into_inner()
}
/// Convenience method for getting the public key as a string
fn public_key_string() -> Base64 {
Base64::new(
PrivateKeyInfo::from_der(&decode_config(PKCS8, STANDARD_NO_PAD).unwrap())
.unwrap()
.public_key
.unwrap()
.to_owned(),
)
Base64::new(PrivateKeyInfo::from_der(&pkcs8()).unwrap().public_key.unwrap().to_owned())
}
/// Convenience for converting a string of JSON into its canonical form.
@ -225,11 +225,7 @@ mod tests {
#[test]
fn sign_empty_json() {
let key_pair = Ed25519KeyPair::from_der(
decode_config(PKCS8, STANDARD_NO_PAD).unwrap().as_slice(),
"1".into(),
)
.unwrap();
let key_pair = Ed25519KeyPair::from_der(&pkcs8(), "1".into()).unwrap();
let mut value = from_json_str("{}").unwrap();
@ -256,11 +252,7 @@ mod tests {
#[test]
fn sign_minimal_json() {
let key_pair = Ed25519KeyPair::from_der(
decode_config(PKCS8, STANDARD_NO_PAD).unwrap().as_slice(),
"1".into(),
)
.unwrap();
let key_pair = Ed25519KeyPair::from_der(&pkcs8(), "1".into()).unwrap();
let mut alpha_object = from_json_str(r#"{ "one": 1, "two": "Two" }"#).unwrap();
sign_json("domain", &key_pair, &mut alpha_object).unwrap();
@ -316,11 +308,7 @@ mod tests {
#[test]
fn sign_minimal_event() {
let key_pair = Ed25519KeyPair::from_der(
decode_config(PKCS8, STANDARD_NO_PAD).unwrap().as_slice(),
"1".into(),
)
.unwrap();
let key_pair = Ed25519KeyPair::from_der(&pkcs8(), "1".into()).unwrap();
let json = r#"{
"room_id": "!x:domain",
@ -350,11 +338,7 @@ mod tests {
#[test]
fn sign_redacted_event() {
let key_pair = Ed25519KeyPair::from_der(
decode_config(PKCS8, STANDARD_NO_PAD).unwrap().as_slice(),
"1".into(),
)
.unwrap();
let key_pair = Ed25519KeyPair::from_der(&pkcs8(), "1".into()).unwrap();
let json = r#"{
"content": {

View File

@ -1,6 +1,6 @@
//! Digital signatures and collections of signatures.
use base64::{encode_config, STANDARD_NO_PAD};
use ruma_common::serde::{base64::Standard, Base64};
use crate::{split_id, Algorithm, Error};
@ -61,7 +61,7 @@ impl Signature {
///
/// Uses the standard character set with no padding.
pub fn base64(&self) -> String {
encode_config(self.signature.as_slice(), STANDARD_NO_PAD)
Base64::<Standard, _>::new(self.signature.as_slice()).encode()
}
/// The key identifier, a string containing the signature algorithm and the key "version"