Upgrade to rand 0.10 and the next RustCrypto generation

`rand` 0.10 and the new RustCrypto generation both build on `rand_core`
0.10, so they have to move together:

 - `rand`, `rand_chacha` and `rand_core` 0.10
 - `digest` 0.11, `sha2` 0.11, `hmac` 0.13, `const-oid` 0.10
 - `elliptic-curve` 0.14, `ecdsa` 0.17, `p256`, `p384` and `k256` 0.14,
   `signature` 3
 - `der`, `spki` and `sec1` 0.8, `pkcs8` 0.11, `pem-rfc7468` 1.0
 - `rsa` 0.10.0-rc.19 and `pkcs1` 0.8.0-rc.5, which have no stable
   release yet. They are pinned exactly, because release candidates
   break their API between releases.
 - `argon2` 0.6 and `pbkdf2` 0.13

On the `rand` side, `RngCore` becomes `Rng` and the old `Rng` becomes
`RngExt`. `gen_*` becomes `random_*`, `thread_rng` becomes `rng`,
`distributions` becomes `distr`, and `from_rng` can no longer fail. On
the crypto side, `mas-jose` and `mas-keystore` move to `BoxedUint` for
RSA, to the `pkcs1` and `pkcs8` reference types, and to the `Generate`
trait for key generation, and `mas-jose` no longer depends on
`generic-array`. Password hashing goes through `hash_password_with_rng`.

Stored data is unaffected. The password hashing snapshots are unchanged,
so bcrypt, Argon2 and PBKDF2 produce the same hashes for the same input
and salt, and `pbkdf2` 0.13 keeps the same defaults (SHA-256, 600 000
rounds). The keystore snapshots change only because keys generated from
a seeded RNG differ. The snapshots of keys loaded from files are
unchanged.

`opa-wasm` 0.3.3 already uses this generation, so most of the duplicate
crates it pulled in go away. The `deny.toml` skip list now names what
still pulls the older versions: cookie, sqlx, headers, wasmtime and pest
for RustCrypto, and opentelemetry_sdk, sentry and ulid for `rand` 0.9.
This commit is contained in:
Quentin Gliech committed 2026-10-09 15:42:26 +02:00
1 parent 9f40244eab
commit 2d3bf03d63
125 files changed
+1026 -717

No files matched your search

Generated
+391 -151
View File
File diff suppressed because it is too large. Load diff
+37 -37
View File
@@ -1,3 +1,4 @@
# Copyright 2025, 2026 Element Creations Ltd.
# Copyright 2025 New Vector Ltd.
#
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -122,12 +123,12 @@ features = ["alloc", "getrandom"]
# Argon2 password hashing
[workspace.dependencies.argon2]
version = "0.5.3"
features = ["password-hash", "std"]
version = "0.6.0"
features = ["alloc", "password-hash", "rand_core"]
# Constant-time base64
[workspace.dependencies.base64ct]
version = "1.8.0"
version = "1.8.3"
features = ["std"]
# Bcrypt password hashing
@@ -180,8 +181,8 @@ features = ["derive"]
# Object Identifiers (OIDs) as constants
[workspace.dependencies.const-oid]
version = "0.9.6"
features = ["std"]
version = "0.10.2"
features = ["db"]
# Utility for converting between different cases
[workspace.dependencies.convert_case]
@@ -201,7 +202,7 @@ version = "1.4.0"
# DER encoding
[workspace.dependencies.der]
version = "0.7.10"
version = "0.8.0"
features = ["std"]
# Interactive CLI dialogs
@@ -212,7 +213,7 @@ features = ["fuzzy-select", "password"]
# Cryptographic digest algorithms
[workspace.dependencies.digest]
version = "0.10.7"
version = "0.11.3"
# Load environment variables from .env files
[workspace.dependencies.dotenvy]
@@ -220,13 +221,13 @@ version = "0.15.7"
# ECDSA algorithms
[workspace.dependencies.ecdsa]
version = "0.16.9"
features = ["signing", "verifying"]
version = "0.17.0"
features = ["alloc", "der", "pem", "pkcs8", "std"]
# Elliptic curve cryptography
[workspace.dependencies.elliptic-curve]
version = "0.13.8"
features = ["std", "pem", "sec1"]
version = "0.14.1"
features = ["std", "pem", "pkcs8", "arithmetic"]
# Configuration loading
[workspace.dependencies.figment]
@@ -241,10 +242,6 @@ version = "1.2.2"
[workspace.dependencies.futures-util]
version = "0.3.31"
# Fixed-size arrays with trait implementations
[workspace.dependencies.generic-array]
version = "0.14.7"
# Rate-limiting
[workspace.dependencies.governor]
version = "0.10.1"
@@ -253,7 +250,7 @@ features = ["std", "dashmap", "quanta"]
# HMAC calculation
[workspace.dependencies.hmac]
version = "0.12.1"
version = "0.13.0"
# HTTP headers
[workspace.dependencies.headers]
@@ -349,8 +346,8 @@ version = "0.15.0"
# K256 elliptic curve
[workspace.dependencies.k256]
version = "0.13.4"
features = ["std"]
version = "0.14.0"
features = ["std", "ecdsa", "pem", "pkcs8"]
# RFC 5646 language tags
[workspace.dependencies.language-tags]
@@ -439,13 +436,13 @@ default-features = false
# P256 elliptic curve
[workspace.dependencies.p256]
version = "0.13.2"
features = ["std"]
version = "0.14.0"
features = ["std", "ecdsa", "pem", "pkcs8"]
# P384 elliptic curve
[workspace.dependencies.p384]
version = "0.13.1"
features = ["std"]
version = "0.14.0"
features = ["std", "ecdsa", "pem", "pkcs8"]
# Text padding utilities
[workspace.dependencies.pad]
@@ -453,12 +450,12 @@ version = "0.1.6"
# PBKDF2 password hashing
[workspace.dependencies.pbkdf2]
version = "0.12.2"
features = ["password-hash", "std", "simple", "parallel"]
version = "0.13.0"
features = ["phc", "sha2", "alloc"]
# PEM encoding/decoding
[workspace.dependencies.pem-rfc7468]
version = "0.7.0"
version = "1.0.0"
features = ["std"]
# Parser generator
@@ -474,14 +471,15 @@ version = "2.8.3"
version = "0.2.16"
# PKCS#1 encoding
# Pinned: release candidates break their API between releases
[workspace.dependencies.pkcs1]
version = "0.7.5"
version = "=0.8.0-rc.5"
features = ["std"]
# PKCS#8 encoding
[workspace.dependencies.pkcs8]
version = "0.10.2"
features = ["std", "pkcs5", "encryption"]
version = "0.11.0"
features = ["std", "pem", "encryption"]
# Public Suffix List
[workspace.dependencies.psl]
@@ -493,11 +491,11 @@ version = "0.12.6"
# Random values
[workspace.dependencies.rand]
version = "0.8.5"
version = "0.10.1"
[workspace.dependencies.rand_chacha]
version = "0.3.1"
version = "0.10.0"
[workspace.dependencies.rand_core]
version = "0.6.4"
version = "0.10.1"
# Regular expressions
[workspace.dependencies.regex]
@@ -518,9 +516,10 @@ features = [
]
# RSA cryptography
# Pinned: release candidates break their API between releases
[workspace.dependencies.rsa]
version = "0.9.10"
features = ["std", "pem"]
version = "=0.10.0-rc.19"
features = ["std", "encoding"]
# Fast hash algorithm for HashMap
[workspace.dependencies.rustc-hash]
@@ -549,7 +548,7 @@ features = ["url2", "chrono04", "preserve_order"]
# SEC1 encoding format
[workspace.dependencies.sec1]
version = "0.7.3"
version = "0.8.1"
features = ["std"]
# Query builder
@@ -607,12 +606,13 @@ version = "0.9.34"
# SHA-2 cryptographic hash algorithm
[workspace.dependencies.sha2]
version = "0.10.9"
version = "0.11.0"
features = ["oid"]
# Digital signature traits
[workspace.dependencies.signature]
version = "2.2.0"
version = "3.0.0"
features = ["alloc", "rand_core"]
# Low-level socket manipulation
[workspace.dependencies.socket2]
@@ -620,7 +620,7 @@ version = "0.6.2"
# Subject Public Key Info
[workspace.dependencies.spki]
version = "0.7.3"
version = "0.8.0"
features = ["std"]
# SQL database support
+2 -1
View File
@@ -1,3 +1,4 @@
# Copyright 2025, 2026 Element Creations Ltd.
# Copyright 2025 New Vector Ltd.
#
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -6,7 +7,7 @@
doc-valid-idents = ["OpenID", "OAuth", "UserInfo", "..", "PostgreSQL", "SQLite"]
disallowed-methods = [
{ path = "rand::thread_rng", reason = "do not create rngs on the fly, pass them as parameters" },
{ path = "rand::rng", reason = "do not create rngs on the fly, pass them as parameters" },
{ path = "chrono::Utc::now", reason = "source the current time from the clock instead" },
# ulid's own constructors/accessors below either use ulid's (separate) `rand`
# or its `std`-only SystemTime API. Use `mas_data_model::UlidExt` instead so our
+9 -5
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -7,7 +8,10 @@
use base64ct::{Base64UrlUnpadded, Encoding};
use chrono::{DateTime, Duration, Utc};
use mas_data_model::Clock;
use rand::{Rng, RngCore, distributions::Standard, prelude::Distribution as _};
use rand::{
Rng, RngExt,
distr::{Distribution as _, StandardUniform},
};
use serde::{Deserialize, Serialize};
use serde_with::{TimestampSeconds, serde_as};
use thiserror::Error;
@@ -55,8 +59,8 @@ impl CsrfToken {
}
/// Generate a new random token valid for a specified duration
fn generate(now: DateTime<Utc>, mut rng: impl Rng, ttl: Duration) -> Self {
let token = Standard.sample(&mut rng);
fn generate(now: DateTime<Utc>, mut rng: impl RngExt, ttl: Duration) -> Self {
let token = StandardUniform.sample(&mut rng);
Self::new(token, now, ttl)
}
@@ -108,7 +112,7 @@ pub trait CsrfExt {
/// if necessary
fn csrf_token<C, R>(self, clock: &C, rng: R) -> (CsrfToken, Self)
where
R: RngCore,
R: Rng,
C: Clock;
/// Verify that the given CSRF-protected form is valid, returning the inner
@@ -126,7 +130,7 @@ pub trait CsrfExt {
impl CsrfExt for CookieJar {
fn csrf_token<C, R>(self, clock: &C, rng: R) -> (CsrfToken, Self)
where
R: RngCore,
R: Rng,
C: Clock,
{
let now = clock.now();
+2 -2
View File
@@ -243,9 +243,9 @@ impl FromRequestParts<AppState> for BoxRng {
) -> impl Future<Output = Result<Self, Self::Rejection>> + Send {
// This rng is used to source the local rng
#[expect(clippy::disallowed_methods)]
let rng = rand::thread_rng();
let mut rng = rand::rng();
let rng = rand_chacha::ChaChaRng::from_rng(rng).expect("Failed to seed RNG");
let rng = rand_chacha::ChaChaRng::from_rng(&mut rng);
let rng: Self = Box::new(rng);
ready(Ok(rng))
}
+5 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -98,8 +99,10 @@ impl Options {
let _span = info_span!("cli.config.generate").entered();
let clock = SystemClock::default();
// XXX: we should disallow SeedableRng::from_entropy
let mut rng = rand_chacha::ChaChaRng::from_entropy();
// Seed the RNG from the thread RNG. `rand::rng()` is normally
// disallowed (we inject RNGs), but this is a top-level entry point.
#[expect(clippy::disallowed_methods)]
let mut rng = rand_chacha::ChaChaRng::from_rng(&mut rand::rng());
let mut config = RootConfig::generate(&mut rng).await?;
if !synapse_config.is_empty() {
+8 -5
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -33,8 +34,8 @@ use mas_storage::{
};
use mas_storage_pg::{DatabaseError, PgRepository};
use rand::{
RngCore, SeedableRng,
distributions::{Alphanumeric, DistString as _},
Rng, SeedableRng,
distr::{Alphanumeric, SampleString as _},
};
use sqlx::{Acquire, types::Uuid};
use tracing::{error, info, info_span, warn};
@@ -222,8 +223,10 @@ impl Options {
pub async fn run(self, figment: &Figment) -> anyhow::Result<ExitCode> {
use Subcommand as SC;
let clock = SystemClock::default();
// XXX: we should disallow SeedableRng::from_entropy
let mut rng = rand_chacha::ChaChaRng::from_entropy();
// Seed the RNG from the thread RNG. `rand::rng()` is normally disallowed
// (we inject RNGs), but this is a top-level entry point.
#[expect(clippy::disallowed_methods)]
let mut rng = rand_chacha::ChaChaRng::from_rng(&mut rand::rng());
match self.subcommand {
SC::SetPassword {
@@ -1112,7 +1115,7 @@ impl UserCreationRequest<'_> {
async fn do_register<E: std::error::Error + Send + Sync + 'static>(
self,
repo: &mut dyn RepositoryAccess<Error = E>,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
) -> Result<User, E> {
let Self {
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -14,7 +15,7 @@ use mas_config::{
UpstreamOAuth2Config,
};
use mas_data_model::SystemClock;
use rand::thread_rng;
use rand::rng;
use sqlx::{Connection, Either, PgConnection, postgres::PgConnectOptions, types::Uuid};
use syn2mas::{
LockedMasDatabase, MasWriter, Progress, ProgressStage, SynapseReader, synapse_config,
@@ -257,7 +258,7 @@ impl Options {
let clock = SystemClock::default();
// TODO is this rng ok?
#[expect(clippy::disallowed_methods)]
let mut rng = thread_rng();
let mut rng = rng();
let progress = Progress::default();
+5 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -73,11 +74,13 @@ impl Options {
} else {
SystemClock::default().now()
};
// `rand::rng()` is normally disallowed (we inject RNGs), but this
// is a top-level entry point.
#[expect(clippy::disallowed_methods)]
let rng = if stabilise {
rand_chacha::ChaChaRng::from_seed([42; 32])
} else {
// XXX: we should disallow SeedableRng::from_entropy
rand_chacha::ChaChaRng::from_entropy()
rand_chacha::ChaChaRng::from_rng(&mut rand::rng())
};
let url_builder =
mas_router::UrlBuilder::new("https://example.com/".parse()?, None, None);
+3 -3
View File
@@ -8,8 +8,8 @@
use anyhow::bail;
use camino::Utf8PathBuf;
use rand::{
Rng,
distributions::{Alphanumeric, DistString},
RngExt,
distr::{Alphanumeric, SampleString},
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -143,7 +143,7 @@ impl MatrixConfig {
pub(crate) fn generate<R>(mut rng: R) -> Self
where
R: Rng + Send,
R: RngExt + Send,
{
Self {
kind: HomeserverKind::default(),
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -6,7 +7,7 @@
use anyhow::bail;
use camino::Utf8PathBuf;
use rand::Rng;
use rand::RngExt;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -172,7 +173,7 @@ impl RootConfig {
/// Returns an error if the secrets could not be generated
pub async fn generate<R>(mut rng: R) -> anyhow::Result<Self>
where
R: Rng + Send,
R: RngExt + Send,
{
Ok(Self {
clients: ClientsConfig::default(),
+10 -7
View File
@@ -12,7 +12,10 @@ use camino::Utf8PathBuf;
use futures_util::future::{try_join, try_join_all};
use mas_jose::jwk::{JsonWebKey, JsonWebKeySet, Thumbprint};
use mas_keystore::{Encrypter, Keystore, PrivateKey};
use rand::{Rng, SeedableRng, distributions::Standard, prelude::Distribution as _};
use rand::{
RngExt, SeedableRng,
distr::{Distribution as _, StandardUniform},
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
@@ -347,12 +350,12 @@ impl SecretsConfig {
#[tracing::instrument(skip_all)]
pub(crate) async fn generate<R>(mut rng: R) -> anyhow::Result<Self>
where
R: Rng + Send,
R: RngExt + Send,
{
info!("Generating keys...");
let span = tracing::info_span!("rsa");
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng)?;
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng);
let rsa_key = task::spawn_blocking(move || {
let _entered = span.enter();
let ret = PrivateKey::generate_rsa(key_rng).unwrap();
@@ -368,7 +371,7 @@ impl SecretsConfig {
};
let span = tracing::info_span!("ec_p256");
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng)?;
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng);
let ec_p256_key = task::spawn_blocking(move || {
let _entered = span.enter();
let ret = PrivateKey::generate_ec_p256(key_rng);
@@ -384,7 +387,7 @@ impl SecretsConfig {
};
let span = tracing::info_span!("ec_p384");
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng)?;
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng);
let ec_p384_key = task::spawn_blocking(move || {
let _entered = span.enter();
let ret = PrivateKey::generate_ec_p384(key_rng);
@@ -400,7 +403,7 @@ impl SecretsConfig {
};
let span = tracing::info_span!("ec_k256");
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng)?;
let key_rng = rand_chacha::ChaChaRng::from_rng(&mut rng);
let ec_k256_key = task::spawn_blocking(move || {
let _entered = span.enter();
let ret = PrivateKey::generate_ec_k256(key_rng);
@@ -416,7 +419,7 @@ impl SecretsConfig {
};
Ok(Self {
encryption: Encryption::Value(Standard.sample(&mut rng)),
encryption: Encryption::Value(StandardUniform.sample(&mut rng)),
keys: Some(vec![rsa_key, ec_p256_key, ec_p384_key, ec_k256_key]),
keys_dir: None,
})
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -6,8 +7,8 @@
use oauth2_types::scope::ScopeToken;
use rand::{
RngCore,
distributions::{Alphanumeric, DistString},
Rng,
distr::{Alphanumeric, SampleString},
};
use serde::{Deserialize, Serialize};
use thiserror::Error;
@@ -58,7 +59,7 @@ impl Device {
}
/// Generate a random device ID
pub fn generate<R: RngCore + ?Sized>(rng: &mut R) -> Self {
pub fn generate<R: Rng + ?Sized>(rng: &mut R) -> Self {
let id: String = Alphanumeric.sample_string(rng, GENERATED_DEVICE_ID_LENGTH);
Self { id }
}
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -14,8 +15,8 @@ use oauth2_types::{
scope::{OPENID, PROFILE, Scope},
};
use rand::{
RngCore,
distributions::{Alphanumeric, DistString},
Rng,
distr::{Alphanumeric, SampleString},
};
use serde::Serialize;
use ulid::Ulid;
@@ -224,7 +225,7 @@ impl AuthorizationGrant {
}
#[doc(hidden)]
pub fn sample(now: DateTime<Utc>, rng: &mut impl RngCore) -> Self {
pub fn sample(now: DateTime<Utc>, rng: &mut impl Rng) -> Self {
Self {
id: Ulid::from_datetime_with_rng(now, rng),
stage: AuthorizationGrantStage::Pending,
+2 -2
View File
@@ -13,7 +13,7 @@ use oauth2_types::{
registration::{ClientMetadata, Localized},
requests::GrantType,
};
use rand::RngCore;
use rand::Rng;
use serde::Serialize;
use thiserror::Error;
use ulid::Ulid;
@@ -181,7 +181,7 @@ impl Client {
}
#[doc(hidden)]
pub fn samples(now: DateTime<Utc>, rng: &mut impl RngCore) -> Vec<Client> {
pub fn samples(now: DateTime<Utc>, rng: &mut impl Rng) -> Vec<Client> {
vec![
// A client with all the URIs set
Self {
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -8,7 +9,7 @@ use std::net::IpAddr;
use chrono::{DateTime, Utc};
use oauth2_types::scope::Scope;
use rand::{Rng, RngCore};
use rand::{Rng, RngExt};
use serde::Serialize;
use ulid::Ulid;
@@ -30,9 +31,9 @@ const USER_CODE_ALPHABET: &[u8; 32] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
const USER_CODE_LENGTH: usize = 6;
/// Generate a random user code for a device code grant.
pub fn generate_user_code<R: RngCore + ?Sized>(rng: &mut R) -> String {
pub fn generate_user_code<R: Rng + ?Sized>(rng: &mut R) -> String {
(0..USER_CODE_LENGTH)
.map(|_| char::from(USER_CODE_ALPHABET[rng.gen_range(0..USER_CODE_ALPHABET.len())]))
.map(|_| char::from(USER_CODE_ALPHABET[rng.random_range(0..USER_CODE_ALPHABET.len())]))
.collect()
}
+5 -4
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -8,7 +9,7 @@ use base64ct::{Base64UrlUnpadded, Encoding};
use chrono::{DateTime, Utc};
use crc::{CRC_32_ISO_HDLC, Crc};
use mas_iana::oauth::OAuthTokenTypeHint;
use rand::{Rng, RngCore, distributions::Alphanumeric};
use rand::{Rng, RngExt, distr::Alphanumeric};
use thiserror::Error;
use ulid::Ulid;
@@ -280,7 +281,7 @@ impl TokenType {
}
/// Generate a token for the given type
pub fn generate(self, rng: &mut (impl RngCore + ?Sized)) -> String {
pub fn generate(self, rng: &mut (impl Rng + ?Sized)) -> String {
let random_part: String = rng
.sample_iter(&Alphanumeric)
.take(30)
@@ -409,7 +410,7 @@ pub enum TokenFormatError {
mod tests {
use std::collections::HashSet;
use rand::thread_rng;
use rand::rng;
use super::*;
@@ -469,7 +470,7 @@ mod tests {
const COUNT: usize = 500; // Generate 500 of each token type
#[expect(clippy::disallowed_methods)]
let mut rng = thread_rng();
let mut rng = rng();
for t in [
TokenType::CompatAccessToken,
+5 -4
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -7,7 +8,7 @@
use std::net::IpAddr;
use chrono::{DateTime, Utc};
use rand::Rng;
use rand::RngExt;
use serde::Serialize;
use ulid::Ulid;
use url::Url;
@@ -57,7 +58,7 @@ impl User {
impl User {
#[doc(hidden)]
#[must_use]
pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self> {
pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl RngExt) -> Vec<Self> {
vec![User {
id: Ulid::from_datetime_with_rng(now, rng),
username: "john".to_owned(),
@@ -173,7 +174,7 @@ impl BrowserSession {
impl BrowserSession {
#[must_use]
pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self> {
pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl RngExt) -> Vec<Self> {
User::samples(now, rng)
.into_iter()
.map(|user| BrowserSession {
@@ -201,7 +202,7 @@ pub struct UserEmail {
impl UserEmail {
#[must_use]
pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self> {
pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl RngExt) -> Vec<Self> {
vec![
Self {
id: Ulid::from_datetime_with_rng(now, rng),
+6 -7
View File
@@ -5,8 +5,7 @@
// Please see LICENSE files in the repository root for full details.
use chrono::{DateTime, Utc};
use rand::Rng;
use rand_chacha::rand_core::CryptoRngCore;
use rand::{CryptoRng, RngExt};
use ulid::Ulid;
use crate::clock::Clock;
@@ -14,7 +13,7 @@ use crate::clock::Clock;
/// A boxed [`Clock`]
pub type BoxClock = Box<dyn Clock + Send>;
/// A boxed random number generator
pub type BoxRng = Box<dyn CryptoRngCore + Send>;
pub type BoxRng = Box<dyn CryptoRng + Send>;
/// Extension trait on [`Ulid`] to build and inspect ULIDs using `chrono`
/// timestamps and an injected RNG.
@@ -25,19 +24,19 @@ pub trait UlidExt: Sized {
/// This reproduces the exact bit layout of `ulid`'s own
/// `Ulid::from_datetime_with_source` (48 timestamp bits, then 80 random
/// bits drawn as a `u16` followed by a `u64`).
fn from_datetime_with_rng<R: Rng + ?Sized>(datetime: DateTime<Utc>, rng: &mut R) -> Self;
fn from_datetime_with_rng<R: RngExt + ?Sized>(datetime: DateTime<Utc>, rng: &mut R) -> Self;
/// The creation timestamp encoded in this [`Ulid`], as a `chrono` datetime.
fn datetime_utc(&self) -> DateTime<Utc>;
}
impl UlidExt for Ulid {
fn from_datetime_with_rng<R: Rng + ?Sized>(datetime: DateTime<Utc>, rng: &mut R) -> Self {
fn from_datetime_with_rng<R: RngExt + ?Sized>(datetime: DateTime<Utc>, rng: &mut R) -> Self {
let timestamp_ms = u64::try_from(datetime.timestamp_millis()).unwrap_or(0);
let timebits = timestamp_ms & ((1 << Ulid::TIME_BITS) - 1);
let msb = timebits << 16 | u64::from(rng.r#gen::<u16>());
let lsb = rng.r#gen::<u64>();
let msb = timebits << 16 | u64::from(rng.random::<u16>());
let lsb = rng.random::<u64>();
Ulid::from(u128::from(msb) << 64 | u128::from(lsb))
}
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
// Copyright 2025 The Matrix.org Foundation C.I.C.
//
@@ -10,7 +11,7 @@ use chrono::{DateTime, Utc};
use hyper::StatusCode;
use mas_axum_utils::record_error;
use mas_data_model::BoxRng;
use rand::distributions::{Alphanumeric, DistString};
use rand::distr::{Alphanumeric, SampleString};
use schemars::JsonSchema;
use serde::Deserialize;
+5 -5
View File
@@ -31,7 +31,7 @@ use mas_storage::{
user::{UserPasswordRepository, UserRepository},
};
use opentelemetry::{Key, KeyValue, metrics::Counter};
use rand::{CryptoRng, RngCore};
use rand::{CryptoRng, Rng};
use serde::{Deserialize, Serialize};
use serde_with::{DurationMilliSeconds, serde_as, skip_serializing_none};
use thiserror::Error;
@@ -533,7 +533,7 @@ pub(crate) async fn post(
/// [`Policy::evaluate_compat_login`], return the appropriate `RouteError`
/// response.
async fn process_violations_for_compat_login(
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
repo: &mut BoxRepository,
session_limit_config: Option<&SessionLimitConfig>,
@@ -772,7 +772,7 @@ async fn find_lru_compat_sessions_flawed(
}
async fn token_login(
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
repo: &mut BoxRepository,
policy: &mut Policy,
@@ -913,7 +913,7 @@ async fn token_login(
}
async fn user_password_login(
mut rng: &mut (impl RngCore + CryptoRng + Send),
mut rng: &mut (impl CryptoRng + Send),
clock: &impl Clock,
password_manager: &PasswordManager,
limiter: &Limiter,
@@ -1036,7 +1036,7 @@ mod tests {
use assert_matches::assert_matches;
use hyper::Request;
use mas_matrix::{HomeserverConnection, ProvisionRequest};
use rand::distributions::{Alphanumeric, DistString};
use rand::distr::{Alphanumeric, SampleString};
use sqlx::PgPool;
use super::*;
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -11,7 +12,7 @@ use mas_axum_utils::{GenericError, InternalError};
use mas_data_model::{BoxClock, BoxRng};
use mas_router::{CompatLoginSsoAction, CompatLoginSsoComplete, UrlBuilder};
use mas_storage::{BoxRepository, compat::CompatSsoLoginRepository};
use rand::distributions::{Alphanumeric, DistString};
use rand::distr::{Alphanumeric, SampleString};
use serde::Deserialize;
use thiserror::Error;
use url::Url;
+3 -3
View File
@@ -46,7 +46,7 @@ use mas_storage::{BoxRepository, BoxRepositoryFactory, RepositoryError};
use opentelemetry_semantic_conventions::trace::{
GRAPHQL_DOCUMENT, GRAPHQL_OPERATION_NAME, GRAPHQL_OPERATION_TYPE,
};
use rand::{SeedableRng, thread_rng};
use rand::{SeedableRng, rng};
use rand_chacha::ChaChaRng;
use state::has_session_ended;
use tracing::{Instrument, info_span};
@@ -125,9 +125,9 @@ impl state::State for GraphQLState {
fn rng(&self) -> BoxRng {
#[expect(clippy::disallowed_methods)]
let rng = thread_rng();
let mut rng = rng();
let rng = ChaChaRng::from_rng(rng).expect("Failed to seed rng");
let rng = ChaChaRng::from_rng(&mut rng);
Box::new(rng)
}
}
@@ -27,7 +27,7 @@ use oauth2_types::{
requests::{AuthorizationRequest, GrantType, Prompt, ResponseMode},
response_type::ResponseType,
};
use rand::{Rng, distributions::Alphanumeric};
use rand::{RngExt, distr::Alphanumeric};
use serde::Deserialize;
use thiserror::Error;
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -23,7 +24,7 @@ use oauth2_types::{
requests::{DeviceAuthorizationRequest, DeviceAuthorizationResponse, GrantType},
scope::ScopeToken,
};
use rand::distributions::{Alphanumeric, DistString};
use rand::distr::{Alphanumeric, SampleString};
use thiserror::Error;
use ulid::Ulid;
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -45,7 +46,7 @@ pub(crate) enum IdTokenSignatureError {
}
pub(crate) fn generate_id_token(
rng: &mut (impl rand::RngCore + rand::CryptoRng),
rng: &mut impl rand::CryptoRng,
clock: &impl Clock,
url_builder: &UrlBuilder,
key_store: &Keystore,
@@ -96,7 +97,7 @@ pub(crate) fn generate_id_token(
}
pub(crate) async fn generate_token_pair<R: RepositoryAccess>(
rng: &mut (impl rand::RngCore + Send),
rng: &mut (impl rand::Rng + Send),
clock: &impl Clock,
repo: &mut R,
session: &Session,
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -25,7 +26,7 @@ use oauth2_types::{
};
use opentelemetry::{Key, KeyValue, metrics::Counter};
use psl::Psl;
use rand::distributions::{Alphanumeric, DistString};
use rand::distr::{Alphanumeric, SampleString};
use serde::Serialize;
use sha2::Digest as _;
use thiserror::Error;
+22 -16
View File
@@ -8,10 +8,13 @@
use std::{collections::HashMap, sync::Arc};
use anyhow::Context;
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier, password_hash::SaltString};
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
use futures_util::future::OptionFuture;
use pbkdf2::{Pbkdf2, password_hash};
use rand::{CryptoRng, RngCore, SeedableRng, distributions::Standard, prelude::Distribution};
use rand::{
CryptoRng, SeedableRng,
distr::{Distribution, StandardUniform},
};
use thiserror::Error;
use zeroize::Zeroizing;
use zxcvbn::zxcvbn;
@@ -163,16 +166,16 @@ impl PasswordManager {
/// Returns an error if the hashing failed or if the password manager is
/// disabled
#[tracing::instrument(name = "passwords.hash", skip_all)]
pub async fn hash<R: CryptoRng + RngCore + Send>(
pub async fn hash<R: CryptoRng + Send>(
&self,
rng: R,
mut rng: R,
password: Zeroizing<String>,
) -> Result<(SchemeVersion, String), anyhow::Error> {
let inner = self.get_inner()?;
// Seed a future-local RNG so the RNG passed in parameters doesn't have to be
// 'static
let rng = rand_chacha::ChaChaRng::from_rng(rng)?;
let rng = rand_chacha::ChaChaRng::from_rng(&mut rng);
let span = tracing::Span::current();
// `inner` is being moved in the blocking task, so we need to copy the version
@@ -230,7 +233,7 @@ impl PasswordManager {
/// Returns an error if the password hash verification failed or if the
/// password manager is disabled
#[tracing::instrument(name = "passwords.verify_and_upgrade", skip_all, fields(%scheme))]
pub async fn verify_and_upgrade<R: CryptoRng + RngCore + Send>(
pub async fn verify_and_upgrade<R: CryptoRng + Send>(
&self,
rng: R,
scheme: SchemeVersion,
@@ -311,7 +314,7 @@ impl Hasher {
}
}
fn hash_blocking<R: CryptoRng + RngCore>(
fn hash_blocking<R: CryptoRng>(
&self,
rng: R,
password: Zeroizing<String>,
@@ -342,7 +345,7 @@ enum Algorithm {
}
impl Algorithm {
fn hash_blocking<R: CryptoRng + RngCore>(
fn hash_blocking<R: CryptoRng>(
self,
mut rng: R,
password: &[u8],
@@ -355,7 +358,7 @@ impl Algorithm {
password.extend_from_slice(pepper);
}
let salt = Standard.sample(&mut rng);
let salt = StandardUniform.sample(&mut rng);
let hashed = bcrypt::hash_with_salt(password, cost.unwrap_or(12), salt)?;
Ok(hashed.format_for_version(bcrypt::Version::TwoB))
@@ -372,8 +375,7 @@ impl Algorithm {
Argon2::new(algorithm, version, params)
};
let salt = SaltString::generate(rng);
let hashed = phf.hash_password(password.as_ref(), &salt)?;
let hashed = phf.hash_password_with_rng(&mut rng, password.as_ref())?;
Ok(hashed.to_string())
}
@@ -383,8 +385,8 @@ impl Algorithm {
password.extend_from_slice(pepper);
}
let salt = SaltString::generate(rng);
let hashed = Pbkdf2.hash_password(password.as_ref(), &salt)?;
let hashed =
Pbkdf2::default().hash_password_with_rng(&mut rng, password.as_ref())?;
Ok(hashed.to_string())
}
}
@@ -422,7 +424,9 @@ impl Algorithm {
match phf.verify_password(password.as_ref(), &hashed_password) {
Ok(()) => PasswordVerificationResult::success(),
Err(password_hash::Error::Password) => PasswordVerificationResult::failure(),
Err(password_hash::Error::PasswordInvalid) => {
PasswordVerificationResult::failure()
}
Err(e) => Err(e)?,
}
}
@@ -435,9 +439,11 @@ impl Algorithm {
let hashed_password = PasswordHash::new(hashed_password)?;
match Pbkdf2.verify_password(password.as_ref(), &hashed_password) {
match Pbkdf2::default().verify_password(password.as_ref(), &hashed_password) {
Ok(()) => PasswordVerificationResult::success(),
Err(password_hash::Error::Password) => PasswordVerificationResult::failure(),
Err(password_hash::Error::PasswordInvalid) => {
PasswordVerificationResult::failure()
}
Err(e) => Err(e)?,
}
}
+3 -3
View File
@@ -18,7 +18,7 @@ use mas_storage::{
personal::PersonalSessionFilter,
};
use mas_templates::{AccountInactiveContext, TemplateContext, Templates};
use rand::RngCore;
use rand::Rng;
use thiserror::Error;
#[derive(Debug, Error)]
@@ -60,7 +60,7 @@ pub fn render_account_inactive(
templates: &Templates,
locale: &DataLocale,
clock: &impl Clock,
rng: impl RngCore,
rng: impl Rng,
cookie_jar: CookieJar,
user: User,
action: Option<PostAuthAction>,
@@ -93,7 +93,7 @@ pub fn render_account_inactive(
pub async fn load_session_or_fallback(
cookie_jar: CookieJar,
clock: &impl Clock,
rng: impl RngCore,
rng: impl Rng,
templates: &Templates,
locale: &DataLocale,
action: Option<PostAuthAction>,
+3 -3
View File
@@ -469,7 +469,7 @@ impl TestState {
/// Panics if the RNG is already locked.
pub fn rng(&self) -> ChaChaRng {
let mut parent_rng = self.rng.try_lock().expect("Failed to lock RNG");
ChaChaRng::from_rng(&mut *parent_rng).unwrap()
ChaChaRng::from_rng(&mut *parent_rng)
}
/// Do a call to the userinfo endpoint to check if the given token is valid.
@@ -546,7 +546,7 @@ impl graphql::State for TestGraphQLState {
fn rng(&self) -> BoxRng {
let mut parent_rng = self.rng.lock().expect("Failed to lock RNG");
let rng = ChaChaRng::from_rng(&mut *parent_rng).expect("Failed to seed RNG");
let rng = ChaChaRng::from_rng(&mut *parent_rng);
Box::new(rng)
}
}
@@ -684,7 +684,7 @@ impl FromRequestParts<TestState> for BoxRng {
state: &TestState,
) -> impl Future<Output = Result<Self, Self::Rejection>> + Send {
let mut parent_rng = state.rng.lock().expect("Failed to lock RNG");
let rng = ChaChaRng::from_rng(&mut *parent_rng).expect("Failed to seed RNG");
let rng = ChaChaRng::from_rng(&mut *parent_rng);
let rng: Self = Box::new(rng);
ready(Ok(rng))
}
+2 -2
View File
@@ -32,7 +32,7 @@ use mas_templates::{
ToFormState,
};
use opentelemetry::{Key, KeyValue, metrics::Counter};
use rand::Rng;
use rand::RngExt;
use serde::{Deserialize, Serialize};
use zeroize::Zeroizing;
@@ -430,7 +430,7 @@ async fn render(
action: OptionalPostAuthAction,
repo: &mut impl RepositoryAccess,
clock: &impl Clock,
rng: impl Rng,
rng: impl RngExt,
templates: &Templates,
homeserver: &dyn HomeserverConnection,
site_config: &SiteConfig,
+1 -1
View File
@@ -1,3 +1,4 @@
# Copyright 2025, 2026 Element Creations Ltd.
# Copyright 2025 New Vector Ltd.
#
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -23,7 +24,6 @@ chrono.workspace = true
digest.workspace = true
ecdsa.workspace = true
elliptic-curve.workspace = true
generic-array.workspace = true
hmac.workspace = true
k256.workspace = true
p256.workspace = true
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -7,7 +8,7 @@
use digest::Digest;
use mas_iana::jose::{JsonWebKeyEcEllipticCurve, JsonWebSignatureAlg};
use sha2::{Sha256, Sha384, Sha512};
use signature::rand_core::CryptoRngCore;
use signature::rand_core::TryCryptoRng;
use thiserror::Error;
use super::signature::Signature;
@@ -231,9 +232,9 @@ impl From<super::Es256KSigningKey> for AsymmetricSigningKey {
}
impl signature::RandomizedSigner<Signature> for AsymmetricSigningKey {
fn try_sign_with_rng(
fn try_sign_with_rng<R: TryCryptoRng + ?Sized>(
&self,
rng: &mut impl CryptoRngCore,
rng: &mut R,
msg: &[u8],
) -> Result<Signature, signature::Error> {
match self {
+17 -16
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -7,32 +8,32 @@
use std::marker::PhantomData;
use digest::{
Digest, Mac, OutputSizeUser,
crypto_common::BlockSizeUser,
generic_array::{ArrayLength, GenericArray},
Digest, KeyInit, Mac, OutputSizeUser,
array::{Array, ArraySize},
block_api::BlockSizeUser,
};
use signature::{Signer, Verifier};
use thiserror::Error;
pub struct Signature<S: ArrayLength<u8>> {
signature: GenericArray<u8, S>,
pub struct Signature<S: ArraySize> {
signature: Array<u8, S>,
}
impl<S: ArrayLength<u8>> PartialEq for Signature<S> {
impl<S: ArraySize> PartialEq for Signature<S> {
fn eq(&self, other: &Self) -> bool {
self.signature == other.signature
}
}
impl<S: ArrayLength<u8>> Eq for Signature<S> {}
impl<S: ArraySize> Eq for Signature<S> {}
impl<S: ArrayLength<u8>> std::fmt::Debug for Signature<S> {
impl<S: ArraySize> std::fmt::Debug for Signature<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.signature)
}
}
impl<S: ArrayLength<u8>> Clone for Signature<S> {
impl<S: ArraySize> Clone for Signature<S> {
fn clone(&self) -> Self {
Self {
signature: self.signature.clone(),
@@ -40,30 +41,30 @@ impl<S: ArrayLength<u8>> Clone for Signature<S> {
}
}
impl<S: ArrayLength<u8>> From<Signature<S>> for GenericArray<u8, S> {
impl<S: ArraySize> From<Signature<S>> for Array<u8, S> {
fn from(val: Signature<S>) -> Self {
val.signature
}
}
impl<'a, S: ArrayLength<u8>> TryFrom<&'a [u8]> for Signature<S> {
impl<'a, S: ArraySize> TryFrom<&'a [u8]> for Signature<S> {
type Error = InvalidLength;
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
if value.len() != S::to_usize() {
return Err(InvalidLength);
}
let mut signature = GenericArray::default();
let mut signature = Array::default();
signature.copy_from_slice(value);
Ok(Self { signature })
}
}
impl<S: ArrayLength<u8>> signature::SignatureEncoding for Signature<S> {
type Repr = GenericArray<u8, S>;
impl<S: ArraySize> signature::SignatureEncoding for Signature<S> {
type Repr = Array<u8, S>;
}
impl<S: ArrayLength<u8>> AsRef<[u8]> for Signature<S> {
impl<S: ArraySize> AsRef<[u8]> for Signature<S> {
fn as_ref(&self) -> &[u8] {
self.signature.as_ref()
}
@@ -104,7 +105,7 @@ impl<D: Digest + BlockSizeUser>
msg: &[u8],
) -> Result<Signature<<hmac::SimpleHmac<D> as OutputSizeUser>::OutputSize>, signature::Error>
{
let mut mac = <hmac::SimpleHmac<D> as Mac>::new_from_slice(&self.key)
let mut mac = <hmac::SimpleHmac<D> as KeyInit>::new_from_slice(&self.key)
.map_err(signature::Error::from_source)?;
mac.update(msg);
let signature = mac.finalize().into_bytes();
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -80,9 +81,9 @@ impl From<super::Hs512Key> for SymmetricKey {
}
impl signature::RandomizedSigner<Signature> for SymmetricKey {
fn try_sign_with_rng(
fn try_sign_with_rng<R: signature::rand_core::TryCryptoRng + ?Sized>(
&self,
_rng: &mut (impl rand::CryptoRng + rand::RngCore),
_rng: &mut R,
msg: &[u8],
) -> Result<Signature, signature::Error> {
// XXX: is that implementation alright?
+10 -9
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -200,7 +201,7 @@ struct RsaOtherPrimeInfo {
}
mod rsa_impls {
use rsa::{BigUint, RsaPrivateKey};
use rsa::{BoxedUint, RsaPrivateKey};
use super::RsaPrivateParameters;
@@ -215,14 +216,14 @@ mod rsa_impls {
type Error = rsa::errors::Error;
fn try_from(value: &RsaPrivateParameters) -> Result<Self, Self::Error> {
let n = BigUint::from_bytes_be(value.n.as_bytes());
let e = BigUint::from_bytes_be(value.e.as_bytes());
let d = BigUint::from_bytes_be(value.d.as_bytes());
let n = BoxedUint::from_be_slice_vartime(value.n.as_bytes());
let e = BoxedUint::from_be_slice_vartime(value.e.as_bytes());
let d = BoxedUint::from_be_slice_vartime(value.d.as_bytes());
let primes = [&value.p, &value.q]
.into_iter()
.chain(value.oth.iter().flatten().map(|o| &o.r))
.map(|i| BigUint::from_bytes_be(i.as_bytes()))
.map(|i| BoxedUint::from_be_slice_vartime(i.as_bytes()))
.collect();
let key = RsaPrivateKey::from_components(n, e, d, primes)?;
@@ -273,7 +274,7 @@ impl From<EcPrivateParameters> for super::public_parameters::EcPublicParameters
mod ec_impls {
use elliptic_curve::{
AffinePoint, Curve, SecretKey,
sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint},
sec1::{Coordinates, FromSec1Point, ModulusSize, ToSec1Point},
};
use super::{super::JwkEcCurve, EcPrivateParameters};
@@ -303,7 +304,7 @@ mod ec_impls {
impl<C> From<SecretKey<C>> for EcPrivateParameters
where
C: elliptic_curve::CurveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize,
{
fn from(key: SecretKey<C>) -> Self {
@@ -314,11 +315,11 @@ mod ec_impls {
impl<C> From<&SecretKey<C>> for EcPrivateParameters
where
C: elliptic_curve::CurveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize,
{
fn from(key: &SecretKey<C>) -> Self {
let point = key.public_key().to_encoded_point(false);
let point = key.public_key().to_sec1_point(false);
let Coordinates::Uncompressed { x, y } = point.coordinates() else {
unreachable!()
};
+17 -17
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -176,7 +177,7 @@ impl OkpPublicParameters {
}
mod rsa_impls {
use rsa::{BigUint, RsaPublicKey, traits::PublicKeyParts};
use rsa::{BoxedUint, RsaPublicKey, traits::PublicKeyParts};
use super::{JsonWebKeyPublicParameters, RsaPublicParameters};
use crate::base64::Base64UrlNoPad;
@@ -202,8 +203,8 @@ mod rsa_impls {
impl From<&RsaPublicKey> for RsaPublicParameters {
fn from(key: &RsaPublicKey) -> Self {
Self {
n: Base64UrlNoPad::new(key.n().to_bytes_be()),
e: Base64UrlNoPad::new(key.e().to_bytes_be()),
n: Base64UrlNoPad::new(key.n().to_be_bytes_trimmed_vartime().into_vec()),
e: Base64UrlNoPad::new(key.e().to_be_bytes_trimmed_vartime().into_vec()),
}
}
}
@@ -218,8 +219,8 @@ mod rsa_impls {
impl TryFrom<&RsaPublicParameters> for RsaPublicKey {
type Error = rsa::errors::Error;
fn try_from(value: &RsaPublicParameters) -> Result<Self, Self::Error> {
let n = BigUint::from_bytes_be(value.n.as_bytes());
let e = BigUint::from_bytes_be(value.e.as_bytes());
let n = BoxedUint::from_be_slice_vartime(value.n.as_bytes());
let e = BoxedUint::from_be_slice_vartime(value.e.as_bytes());
let key = RsaPublicKey::new(n, e)?;
Ok(key)
}
@@ -228,10 +229,9 @@ mod rsa_impls {
mod ec_impls {
use digest::typenum::Unsigned;
use ecdsa::EncodedPoint;
use elliptic_curve::{
AffinePoint, FieldBytes, PublicKey,
sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint},
sec1::{Coordinates, FromSec1Point, ModulusSize, Sec1Point, ToSec1Point},
};
use super::{super::JwkEcCurve, EcPublicParameters, JsonWebKeyPublicParameters};
@@ -240,7 +240,7 @@ mod ec_impls {
impl<C> TryFrom<&EcPublicParameters> for PublicKey<C>
where
C: elliptic_curve::CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize + Unsigned,
{
type Error = elliptic_curve::Error;
@@ -256,10 +256,10 @@ mod ec_impls {
.get(..C::FieldBytesSize::USIZE)
.ok_or(elliptic_curve::Error)?;
let x = FieldBytes::<C>::from_slice(x);
let y = FieldBytes::<C>::from_slice(y);
let pubkey = EncodedPoint::<C>::from_affine_coordinates(x, y, false);
let pubkey: Option<_> = PublicKey::from_encoded_point(&pubkey).into();
let x = FieldBytes::<C>::try_from(x).map_err(|_| elliptic_curve::Error)?;
let y = FieldBytes::<C>::try_from(y).map_err(|_| elliptic_curve::Error)?;
let pubkey = Sec1Point::<C>::from_affine_coordinates(&x, &y, false);
let pubkey: Option<_> = PublicKey::from_sec1_point(&pubkey).into();
pubkey.ok_or(elliptic_curve::Error)
}
}
@@ -267,7 +267,7 @@ mod ec_impls {
impl<C> From<PublicKey<C>> for JsonWebKeyPublicParameters
where
C: elliptic_curve::CurveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize,
{
fn from(key: PublicKey<C>) -> Self {
@@ -278,7 +278,7 @@ mod ec_impls {
impl<C> From<&PublicKey<C>> for JsonWebKeyPublicParameters
where
C: elliptic_curve::CurveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize,
{
fn from(key: &PublicKey<C>) -> Self {
@@ -289,7 +289,7 @@ mod ec_impls {
impl<C> From<PublicKey<C>> for EcPublicParameters
where
C: elliptic_curve::CurveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize,
{
fn from(key: PublicKey<C>) -> Self {
@@ -300,11 +300,11 @@ mod ec_impls {
impl<C> From<&PublicKey<C>> for EcPublicParameters
where
C: elliptic_curve::CurveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
C::FieldBytesSize: ModulusSize,
{
fn from(key: &PublicKey<C>) -> Self {
let point = key.to_encoded_point(false);
let point = key.to_sec1_point(false);
let Coordinates::Uncompressed { x, y } = point.coordinates() else {
unreachable!()
};
+10 -6
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -5,9 +6,9 @@
// Please see LICENSE files in the repository root for full details.
use base64ct::{Base64UrlUnpadded, Encoding};
use rand::thread_rng;
use rand::rng;
use serde::{Serialize, de::DeserializeOwned};
use signature::{RandomizedSigner, SignatureEncoding, Verifier, rand_core::CryptoRngCore};
use signature::{RandomizedSigner, SignatureEncoding, Verifier, rand_core::CryptoRng};
use thiserror::Error;
use super::{header::JsonWebSignatureHeader, raw::RawJwt};
@@ -325,7 +326,7 @@ impl<T> Jwt<'static, T> {
T: Serialize,
{
#[expect(clippy::disallowed_methods)]
Self::sign_with_rng(&mut thread_rng(), header, payload, key)
Self::sign_with_rng(&mut rng(), header, payload, key)
}
/// Sign the given payload with the given key using the given RNG.
@@ -341,7 +342,7 @@ impl<T> Jwt<'static, T> {
key: &K,
) -> Result<Self, JwtSignatureError>
where
R: CryptoRngCore,
R: CryptoRng,
K: RandomizedSigner<S>,
S: SignatureEncoding,
T: Serialize,
@@ -378,7 +379,7 @@ impl<T> Jwt<'static, T> {
mod tests {
#![allow(clippy::disallowed_methods)]
use mas_iana::jose::JsonWebSignatureAlg;
use rand::thread_rng;
use rand::rng;
use super::*;
@@ -406,7 +407,10 @@ mod tests {
let header = JsonWebSignatureHeader::new(JsonWebSignatureAlg::Es256);
let payload = serde_json::json!({"hello": "world"});
let key = ecdsa::SigningKey::<p256::NistP256>::random(&mut thread_rng());
let key =
<ecdsa::SigningKey<p256::NistP256> as elliptic_curve::Generate>::generate_from_rng(
&mut rng(),
);
let signed = Jwt::sign::<_, ecdsa::Signature<_>>(header, payload, &key).unwrap();
signed
.verify::<_, ecdsa::Signature<_>>(key.verifying_key())
+39 -39
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -8,19 +9,18 @@
use std::{ops::Deref, sync::Arc};
use der::{Decode, Encode, EncodePem, zeroize::Zeroizing};
use elliptic_curve::{pkcs8::EncodePrivateKey, sec1::ToEncodedPoint};
use der::{Decode, Encode, EncodePem, pem::PemLabel, zeroize::Zeroizing};
use elliptic_curve::{Generate, pkcs8::EncodePrivateKey, sec1::ToSec1Point};
use mas_iana::jose::{JsonWebKeyType, JsonWebSignatureAlg};
pub use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
use mas_jose::{
jwa::{AsymmetricSigningKey, AsymmetricVerifyingKey},
jwk::{JsonWebKeyPublicParameters, ParametersInfo, PublicJsonWebKeySet, Thumbprint},
};
use pem_rfc7468::PemLabel;
use pkcs1::EncodeRsaPrivateKey;
use pkcs8::{AssociatedOid, PrivateKeyInfo};
use rand::{CryptoRng, RngCore};
use rsa::BigUint;
use pkcs8::{AssociatedOid, PrivateKeyInfoRef};
use rand::CryptoRng;
use rsa::BoxedUint;
use thiserror::Error;
mod encrypter;
@@ -133,7 +133,7 @@ pub enum PrivateKey {
pub struct WrongAlgorithmError;
impl PrivateKey {
fn from_pkcs1_private_key(pkcs1_key: &pkcs1::RsaPrivateKey) -> Result<Self, LoadError> {
fn from_pkcs1_private_key(pkcs1_key: &pkcs1::RsaPrivateKeyRef<'_>) -> Result<Self, LoadError> {
// Taken from `TryFrom<pkcs8::PrivateKeyInfo<'_>> for RsaPrivateKey`
// Multi-prime RSA keys not currently supported
@@ -141,17 +141,17 @@ impl PrivateKey {
return Err(pkcs1::Error::Version.into());
}
let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes());
let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes());
let d = BigUint::from_bytes_be(pkcs1_key.private_exponent.as_bytes());
let first_prime = BigUint::from_bytes_be(pkcs1_key.prime1.as_bytes());
let second_prime = BigUint::from_bytes_be(pkcs1_key.prime2.as_bytes());
let n = BoxedUint::from_be_slice_vartime(pkcs1_key.modulus.as_bytes());
let e = BoxedUint::from_be_slice_vartime(pkcs1_key.public_exponent.as_bytes());
let d = BoxedUint::from_be_slice_vartime(pkcs1_key.private_exponent.as_bytes());
let first_prime = BoxedUint::from_be_slice_vartime(pkcs1_key.prime1.as_bytes());
let second_prime = BoxedUint::from_be_slice_vartime(pkcs1_key.prime2.as_bytes());
let primes = vec![first_prime, second_prime];
let key = rsa::RsaPrivateKey::from_components(n, e, d, primes)?;
Ok(Self::Rsa(Box::new(key)))
}
fn from_private_key_info(info: PrivateKeyInfo) -> Result<Self, LoadError> {
fn from_private_key_info(info: PrivateKeyInfoRef<'_>) -> Result<Self, LoadError> {
match info.algorithm.oid {
pkcs1::ALGORITHM_OID => Ok(Self::Rsa(Box::new(info.try_into()?))),
elliptic_curve::ALGORITHM_OID => match info.algorithm.parameters_oid()? {
@@ -287,16 +287,16 @@ impl PrivateKey {
/// - the key could not be decrypted
/// - the PKCS8 key could not be loaded
pub fn load_encrypted_der(der: &[u8], password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
if let Ok(info) = pkcs8::EncryptedPrivateKeyInfo::from_der(der) {
if let Ok(info) = pkcs8::EncryptedPrivateKeyInfoRef::from_der(der) {
let decrypted = info.decrypt(password)?;
return Self::load_der(decrypted.as_bytes()).map_err(|inner| LoadError::InEncrypted {
inner: Box::new(inner),
});
}
if pkcs8::PrivateKeyInfo::from_der(der).is_ok()
if pkcs8::PrivateKeyInfoRef::from_der(der).is_ok()
|| sec1::EcPrivateKey::from_der(der).is_ok()
|| pkcs1::RsaPrivateKey::from_der(der).is_ok()
|| pkcs1::RsaPrivateKeyRef::from_der(der).is_ok()
{
return Err(LoadError::Unencrypted);
}
@@ -317,11 +317,11 @@ impl PrivateKey {
/// - the PKCS8/SEC1/PKCS1 key could not be loaded
pub fn load_der(der: &[u8]) -> Result<Self, LoadError> {
// Let's try evey known DER format one after the other
if pkcs8::EncryptedPrivateKeyInfo::from_der(der).is_ok() {
if pkcs8::EncryptedPrivateKeyInfoRef::from_der(der).is_ok() {
return Err(LoadError::Encrypted);
}
if let Ok(info) = pkcs8::PrivateKeyInfo::from_der(der) {
if let Ok(info) = pkcs8::PrivateKeyInfoRef::from_der(der) {
return Self::from_private_key_info(info);
}
@@ -329,7 +329,7 @@ impl PrivateKey {
return Self::from_ec_private_key(info);
}
if let Ok(pkcs1_key) = pkcs1::RsaPrivateKey::from_der(der) {
if let Ok(pkcs1_key) = pkcs1::RsaPrivateKeyRef::from_der(der) {
return Self::from_pkcs1_private_key(&pkcs1_key);
}
@@ -351,16 +351,16 @@ impl PrivateKey {
let (label, doc) = pem_rfc7468::decode_vec(pem.as_bytes())?;
match label {
pkcs8::EncryptedPrivateKeyInfo::PEM_LABEL => {
let info = pkcs8::EncryptedPrivateKeyInfo::from_der(&doc)?;
pkcs8::EncryptedPrivateKeyInfoRef::PEM_LABEL => {
let info = pkcs8::EncryptedPrivateKeyInfoRef::from_der(&doc)?;
let decrypted = info.decrypt(password)?;
Self::load_der(decrypted.as_bytes()).map_err(|inner| LoadError::InEncrypted {
inner: Box::new(inner),
})
}
pkcs1::RsaPrivateKey::PEM_LABEL
| pkcs8::PrivateKeyInfo::PEM_LABEL
pkcs1::RsaPrivateKeyRef::PEM_LABEL
| pkcs8::PrivateKeyInfoRef::PEM_LABEL
| sec1::EcPrivateKey::PEM_LABEL => Err(LoadError::Unencrypted),
label => Err(LoadError::UnsupportedPemLabel {
@@ -383,13 +383,13 @@ impl PrivateKey {
let (label, doc) = pem_rfc7468::decode_vec(pem.as_bytes())?;
match label {
pkcs1::RsaPrivateKey::PEM_LABEL => {
let pkcs1_key = pkcs1::RsaPrivateKey::from_der(&doc)?;
pkcs1::RsaPrivateKeyRef::PEM_LABEL => {
let pkcs1_key = pkcs1::RsaPrivateKeyRef::from_der(&doc)?;
Self::from_pkcs1_private_key(&pkcs1_key)
}
pkcs8::PrivateKeyInfo::PEM_LABEL => {
let info = pkcs8::PrivateKeyInfo::from_der(&doc)?;
pkcs8::PrivateKeyInfoRef::PEM_LABEL => {
let info = pkcs8::PrivateKeyInfoRef::from_der(&doc)?;
Self::from_private_key_info(info)
}
@@ -398,7 +398,7 @@ impl PrivateKey {
Self::from_ec_private_key(key)
}
pkcs8::EncryptedPrivateKeyInfo::PEM_LABEL => Err(LoadError::Encrypted),
pkcs8::EncryptedPrivateKeyInfoRef::PEM_LABEL => Err(LoadError::Encrypted),
label => Err(LoadError::UnsupportedPemLabel {
label: label.to_owned(),
@@ -495,26 +495,26 @@ impl PrivateKey {
/// # Errors
///
/// Returns any error from the underlying key generator
pub fn generate_rsa<R: RngCore + CryptoRng>(mut rng: R) -> Result<Self, rsa::errors::Error> {
pub fn generate_rsa<R: CryptoRng>(mut rng: R) -> Result<Self, rsa::errors::Error> {
let key = rsa::RsaPrivateKey::new(&mut rng, 2048)?;
Ok(Self::Rsa(Box::new(key)))
}
/// Generate an Elliptic Curve key for the P-256 curve
pub fn generate_ec_p256<R: RngCore + CryptoRng>(mut rng: R) -> Self {
let key = elliptic_curve::SecretKey::random(&mut rng);
pub fn generate_ec_p256<R: CryptoRng>(mut rng: R) -> Self {
let key = elliptic_curve::SecretKey::generate_from_rng(&mut rng);
Self::EcP256(Box::new(key))
}
/// Generate an Elliptic Curve key for the P-384 curve
pub fn generate_ec_p384<R: RngCore + CryptoRng>(mut rng: R) -> Self {
let key = elliptic_curve::SecretKey::random(&mut rng);
pub fn generate_ec_p384<R: CryptoRng>(mut rng: R) -> Self {
let key = elliptic_curve::SecretKey::generate_from_rng(&mut rng);
Self::EcP384(Box::new(key))
}
/// Generate an Elliptic Curve key for the secp256k1 curve
pub fn generate_ec_k256<R: RngCore + CryptoRng>(mut rng: R) -> Self {
let key = elliptic_curve::SecretKey::random(&mut rng);
pub fn generate_ec_k256<R: CryptoRng>(mut rng: R) -> Self {
let key = elliptic_curve::SecretKey::generate_from_rng(&mut rng);
Self::EcK256(Box::new(key))
}
}
@@ -525,11 +525,11 @@ impl PrivateKey {
fn to_sec1_der<C>(key: &elliptic_curve::SecretKey<C>) -> Result<Zeroizing<Vec<u8>>, der::Error>
where
C: elliptic_curve::Curve + elliptic_curve::CurveArithmetic + AssociatedOid,
elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToEncodedPoint<C>,
elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToSec1Point<C>,
C::FieldBytesSize: elliptic_curve::sec1::ModulusSize,
{
let private_key_bytes = Zeroizing::new(key.to_bytes());
let public_key_bytes = key.public_key().to_encoded_point(false);
let public_key_bytes = key.public_key().to_sec1_point(false);
Ok(Zeroizing::new(
sec1::EcPrivateKey {
private_key: &private_key_bytes,
@@ -546,11 +546,11 @@ fn to_sec1_pem<C>(
) -> Result<Zeroizing<String>, der::Error>
where
C: elliptic_curve::Curve + elliptic_curve::CurveArithmetic + AssociatedOid,
elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToEncodedPoint<C>,
elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToSec1Point<C>,
C::FieldBytesSize: elliptic_curve::sec1::ModulusSize,
{
let private_key_bytes = Zeroizing::new(key.to_bytes());
let public_key_bytes = key.public_key().to_encoded_point(false);
let public_key_bytes = key.public_key().to_sec1_point(false);
Ok(Zeroizing::new(
sec1::EcPrivateKey {
private_key: &private_key_bytes,
@@ -1,10 +1,9 @@
---
source: crates/keystore/tests/keystore.rs
expression: "ec_p256.to_pem(LineEnding::LF).unwrap()"
expression: "&*ec_p256.to_pem(LineEnding::LF).unwrap()"
---
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIH3L+ZYgfEaJtclP07qPQBrmkHEhYkyYooxvU8AlSW+CoAoGCCqGSM49
AwEHoUQDQgAEXcA+X+lhDCmmzaUQFh7i7gkT7mwdrRUsMl9RSfyWh93n+xq3O4/m
vMmUnlvy7tBoHkcAdTJ+Zkv+loLw+mkcBA==
MHcCAQEEILI2J4kLaLQCw/EUtQupK0g4Hd5K2rpL7DPf8JxJR8sXoAoGCCqGSM49
AwEHoUQDQgAExoXwK0I+5KIXMQcact2A5BTX8T8UDH5zHCBL7hKxO6y69kAn2NIP
9VZgChemq1baX+/4eZMgYbsFjjZxCepjFw==
-----END EC PRIVATE KEY-----
@@ -1,11 +1,10 @@
---
source: crates/keystore/tests/keystore.rs
expression: "ec_p384.to_pem(LineEnding::LF).unwrap()"
expression: "&*ec_p384.to_pem(LineEnding::LF).unwrap()"
---
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAl3R97SR8hWLuMH6737YdvXVb7P7T9pKSIhQozmzN+r+V5Ncvjn+DQ
Q/QxYr9nLwOgBwYFK4EEACKhZANiAASa86XQW7CDF9GhvcBY53sJ4lP0z9rfrjwo
nwixQJIWBROjlpsm5hdIwLfj46IUPYCNEoD8VP8eR2s/uzlgEv1hnz/2wmLlMqU0
2R5QcY7Gc9CyDTO1bh5V2FFYjks4xfs=
MIGkAgEBBDDSnZxO7HGescWZ8Lx5EnOSp/ep8AeJi5Phq3DGbqshMxDMIE89tQz5
bKFDIry98DCgBwYFK4EEACKhZANiAAQvXEB4cXKh8IOp3H7DGeBEMl7tpkROyGqh
bcdbCIZ55BookRp7GpfUldNOW/z/iLs5m8as3P6h+2GtvmxitErGxLe+ziBh4MCH
/FiUkahhEaRkZN3wZax5cquzSESgYns=
-----END EC PRIVATE KEY-----
@@ -1,10 +1,9 @@
---
source: crates/keystore/tests/keystore.rs
expression: "ec_k256.to_pem(LineEnding::LF).unwrap()"
expression: "&*ec_k256.to_pem(LineEnding::LF).unwrap()"
---
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIBcikq9QkV39T8VFZWD4j5wO9xm0FWxhuAmvDRpix8XUoAcGBSuBBAAK
oUQDQgAEf4htTtPsdxlZn1htWE3ueHT4JB/4n4lxVOQdT/3RFuCS5aKQ04oS9pKM
QAHAn1bjbLRQ88Yxi3CgHuCitS+RrA==
MHQCAQEEILWCa5ChwVAT7+XP9fGxVPzVBEE9SiFmzQrUYujA+qxPoAcGBSuBBAAK
oUQDQgAEljNWxpBfmKyeamlQsZHUq7Npp3a7NwI4tVTtZi10UvZSccc8LeOoJoFW
KneiunxfPzfWhQQH/ChWKtAAyrdm5Q==
-----END EC PRIVATE KEY-----
@@ -4,18 +4,17 @@ expression: jwks
---
keys:
- kty: RSA
n: vClyfM076hWBZonjThx_PX46UQUWb2LfOpUV1655ZGoKMKgqanLMMfLBPjW9ouY6UtrZ7BxEgl01xLZ1dLdD2Ggb2IpwW56PUuZD2w9hJMungjR0ImymFBwjA9j2ucr0eIHdVQoOakEsrB0dqEC-3R7ax7piGCj9YB6uGZbDVfIJUv40o1pb-hvmmyQHwpoU4jR1y_V-OhrdFMPtwCXov2nlrqDb_e-T7TQlu4FN0URI6VxLNcSkgZfJH50PdJPr7AHqtnWhOGBfLaC9jDpGxfbjmC1iSMSzOt6WyVdcnqHv_JpzXu0SzFqpUSm3OI_l2DUjwTJBL1TOIRTVsjQN1w
n: yiR2hY43e0aMz4lhaQvnyjlbVhudk6KexRnJ35Cz5X_yifzlr2Ui006UOKoWPJoUCFrwOXC-rGnPlzqYDtjOLKWWvMdNUyIwfGoovRxqRrcoAHKl76Iuq9DFFSksI_aFmpwltVZaUbrsg6q8ptQ_E9uZfb7lTNoFBhjA3VUPhlWAQEvBpo78YlB8rD8z-OqAN92JeYM841c1r4W3-U9H7g9WuBO2FMedA0Zl1k2MEz50NcGUUe8YB1GcV8IsP2RiTKd8PwsjlM37xQ2j_l4MuU0zxXfWw35ukSjpQaOJcyU9FTLj6f-reLH0gpVCq8N4qRNQsbEhDxaJNE-VnDYMew
e: AQAB
- kty: EC
crv: P-256
x: XcA-X-lhDCmmzaUQFh7i7gkT7mwdrRUsMl9RSfyWh90
y: 5_satzuP5rzJlJ5b8u7QaB5HAHUyfmZL_paC8PppHAQ
x: xoXwK0I-5KIXMQcact2A5BTX8T8UDH5zHCBL7hKxO6w
y: uvZAJ9jSD_VWYAoXpqtW2l_v-HmTIGG7BY42cQnqYxc
- kty: EC
crv: P-384
x: mvOl0FuwgxfRob3AWOd7CeJT9M_a3648KJ8IsUCSFgUTo5abJuYXSMC34-OiFD2A
y: jRKA_FT_HkdrP7s5YBL9YZ8_9sJi5TKlNNkeUHGOxnPQsg0ztW4eVdhRWI5LOMX7
x: L1xAeHFyofCDqdx-wxngRDJe7aZETshqoW3HWwiGeeQaKJEaexqX1JXTTlv8_4i7
y: OZvGrNz-ofthrb5sYrRKxsS3vs4gYeDAh_xYlJGoYRGkZGTd8GWseXKrs0hEoGJ7
- kty: EC
crv: secp256k1
x: f4htTtPsdxlZn1htWE3ueHT4JB_4n4lxVOQdT_3RFuA
y: kuWikNOKEvaSjEABwJ9W42y0UPPGMYtwoB7gorUvkaw
x: ljNWxpBfmKyeamlQsZHUq7Npp3a7NwI4tVTtZi10UvY
y: UnHHPC3jqCaBVip3orp8Xz831oUEB_woVirQAMq3ZuU
@@ -1,32 +1,31 @@
---
source: crates/keystore/tests/keystore.rs
expression: "rsa.to_pem(LineEnding::LF).unwrap()"
expression: "&*rsa.to_pem(LineEnding::LF).unwrap()"
---
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvClyfM076hWBZonjThx/PX46UQUWb2LfOpUV1655ZGoKMKgq
anLMMfLBPjW9ouY6UtrZ7BxEgl01xLZ1dLdD2Ggb2IpwW56PUuZD2w9hJMungjR0
ImymFBwjA9j2ucr0eIHdVQoOakEsrB0dqEC+3R7ax7piGCj9YB6uGZbDVfIJUv40
o1pb+hvmmyQHwpoU4jR1y/V+OhrdFMPtwCXov2nlrqDb/e+T7TQlu4FN0URI6VxL
NcSkgZfJH50PdJPr7AHqtnWhOGBfLaC9jDpGxfbjmC1iSMSzOt6WyVdcnqHv/Jpz
Xu0SzFqpUSm3OI/l2DUjwTJBL1TOIRTVsjQN1wIDAQABAoIBAD4bcC7Bj4U0lAHE
gcLGpTkm8RjNFRqvB//ONed7L5Z1aeelmlqIid3ywtZF5tJeK+ItWsEUk4h0O8sy
bpKX600DEC3phCy5qZUzbDJiYS5ECoZvyeWS9z6sCuK6OrYYx5j/RI9NQnTQDm7B
LYjb1iQmixBh9P8EiJ2xgsXvfYpgSDv2nUBVywp8HUmadAqE89cBsyurvMpR6eY4
HI0Wge+vIbh0KHj5h7sJ7C8mWBcnjkJ9hWSCumMth3wufEpfs4lCUjhojTkr6ioT
9Mok8VpZvsxzDw3Ubnut1lX7II2EYwNEfgm/Tcw4/NC2eLc1AjoshxLVLg5JWy85
RGj7FAECgYEAyLTpdQjD0PrQBi6O5HWQnVMVvJQz6bihdKUrjwJOfWvqgKVpAVVQ
IbLUT3J6ooe4Tei6xc7viNA7JZ+KyRvaQuZT4nWW2AkOCOnaxH3NKI4cDpWsdNdC
jNBHnIUUvDU4c4CkgIc8f1Gezm9epDVsgb1+wxwSbB8Je4S7M8is1WUCgYEA7//M
f1UPl32yaXH7ag8DbWHMzeNRw5T+F3zTagp93mCM0mPYyjggMfwPFr7167ISWrG4
6DfHHABqhjnAkKfrrFMN5Xm8oup60XXIox1FB4Ew4K0VzyMTnSMPMMEGJZx6VQJP
TlGpexs4t+1N/gWgcGv1OgZ+fw7hjcaFtTMAcIsCgYBY/W3tyF8aT7rgotAUl9Px
DZ+7p3KFFKnx0DJKDFnE3o5xT+YJA0yuRF5Cg53AZrDfSmtVvXUTklBHVD/y/3h8
5ScYZ87kJs+kQBwRtz2515i1FsQKYk9NpCO8UH1rHaXUAJvvqQa35PamzVaHNHDR
7bVAyTeZ3QEVVTqzsSyAyQKBgQDDIcL+QIW10VBPJYqZ9+z8cUkYmVuwXqKdLDOk
gzVFqlC0+tOXzzx2B4+pGchPQ3Bi5x8FR9yOqtPxoGEt/CnE6Z5h1rIF8Am95jsk
TDcE3AiGlJQn30giOhAuvrIlwG1CUudyMTlQS5i5Cquf/qks3sn6zK7q1YmUQTYT
Vo1j8wKBgQCgSISkWgRrQhEdZKBBzcxkWyUXUMieZa+pPTooZGY1VAqyTSXHUlLi
mrWtJ4temNK6OE7xAWJMWL6cVAxQUrs8C11DS//IGMxlMF/7uMU6pOFmMqq52G3D
k3NkZSJmC1liFiu3Q6Q2UqGHRX8CS5MeLncReuNUnFOiX8X2fcjoRw==
MIIEpQIBAAKCAQEAyiR2hY43e0aMz4lhaQvnyjlbVhudk6KexRnJ35Cz5X/yifzl
r2Ui006UOKoWPJoUCFrwOXC+rGnPlzqYDtjOLKWWvMdNUyIwfGoovRxqRrcoAHKl
76Iuq9DFFSksI/aFmpwltVZaUbrsg6q8ptQ/E9uZfb7lTNoFBhjA3VUPhlWAQEvB
po78YlB8rD8z+OqAN92JeYM841c1r4W3+U9H7g9WuBO2FMedA0Zl1k2MEz50NcGU
Ue8YB1GcV8IsP2RiTKd8PwsjlM37xQ2j/l4MuU0zxXfWw35ukSjpQaOJcyU9FTLj
6f+reLH0gpVCq8N4qRNQsbEhDxaJNE+VnDYMewIDAQABAoIBACC/QXgnbvOInV0t
u1siM52+Jv7PIHr/WEtD/0E5lvsx/B/AmZENiFPFIhv/6fRNXbtwyAP2MN2LkrbE
JkgZdWUkOkRA4VT7b/Fn3Uuto8Xq/A7+g8VLd9YbzyG7dsworsI6U52J7L3a02AN
M9yu+70C0V3epBUMKM4xCmWQ1yACxim7NHzMa9tFzYPzZjQ7icDoY2Ku+Yh60HOc
HudGcw3T4QM4XYT4rubUnVA8iUWlFmqhSqJoaNXo5hZ4a5kmZJndTj9PsgZrweG/
nksx7HVrljwOEUhFAr5TeOxwzIPiOaFPrKMHz7gux6S1hg5av/EgZFHWcG69bSsp
Oqk0ockCgYEA7dviO07nt6S6komg5ScXqpfNcY7FmANN9P1Qc5XHQC3m3JKbYOhb
o4HCBveJVgYoPRPsg9NLMZjFcI9ioM4MAM3Kmw0qEiiETtu/AVCHExQmY7RbpF2C
nknhSdi8tkKwoJqy+VgWZ1JtcbcIxbZTjPNFP8YleZGIrpC/tTldXS0CgYEA2Y86
Ct0FRDesm/5Igz+jF66fjeuyVIWnrAijA4qVsanCaeqaVljOvdb7jdgv+xFxQwa8
tGSfPZcJ2CDaXvdKBBQSYdGmAk1Csx7AhEcqGTlSB8AunEqVxSeRIo77TB63E45c
YETiww1xrWnwMrIk/yv4nQ4arobjk0z3Gv4ZKUcCgYEAkiItc9Keei0ykyULPL4v
xBdPmRzmOOaO1p1q+BhlOgD5fTp1S6x14Jav5ifesINH5X6AKN1/rRD2/JibN8Bf
j37fozMLTeymnOxVBTG8SvRuQYNlai4pOaaaSwxlpHSEn6drndWIriHuK5cQRKgn
3Mj5Gp1aGL5ZAybbITQFMGECgYEAsIq+IeSainHXOrqMoxy3vtbwGJ1Dl7zhhAN6
LLx/nqzP210JornsAjb66G6e+NB9pVNJO+VPJw5yaZS3P0rSIB8dj40tdj61ul5h
ALYy3kcaXrm/2QnZISRrbKy0FV/zVgY2xdQAYyF8tqj5xlmzFfHbi67PTgKdl4Fk
H95EEq8CgYEAtnRVj6QTwewhyrohk7Um4hNDTztWsl/fp5nXLt6oMpdTpSNcZ8mN
BL9tkexGnVkFUFuLDFih5lR3vfWybgW5SYeqtPTN6H1WILg4/+hzz9Q7rocsD8IS
fvPh2AABTi/IG3o5LYYIhc2i6D+dgOIJIz9mSq8tEG19umGOcQrfC2w=
-----END RSA PRIVATE KEY-----
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJFUzI1NiJ9.IiI.Yvudbc_oPln_H02H9woFZurQrgzsuWGnRK2kZzat_rp2HYFZtYobvMw9LqPDgeqq9a1HiL_Hx796SqyobiTXJg
eyJhbGciOiJFUzI1NiJ9.IiI.1bCvHBi8U9PPx2AeivKsulmaWl3lBebZLkOmsDuEfgg-xDk70BiFMVYa_K3cB6eLJ4YevF8699mOPvoJTZHvxg
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJFUzI1NksifQ.IiI.4q4ua7R-we5m58rKtLQDHJmQJb15dEUhj7A_H5kh591mrScXFmCYXVQI5iKKXGFHBV_AFISrJF4YjWCHDnLPeQ
eyJhbGciOiJFUzI1NksifQ.IiI.OZ2SAGjxchqzA-QlD5Ejp-Vbt4WFPvWX7x9mkeeuu6c6I1xFTyXZrk7MKp7DdQX4pxb_swhlhzU4DEDLgRrBLw
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJFUzM4NCJ9.IiI.p9Otttjs3JOxZCeuIKwkql3YM-nfdxo__EVt84sex_PcokYjY47sa0qsvCqUUhpUoLSBihdchynuYqc5lOFuAM3Pi2pjg-ZrTqrzI23UlzFonlr4Zag9Qo3IYD10HKFq
eyJhbGciOiJFUzM4NCJ9.IiI.Yve7Rrfz6HK76aL_gQB8CchNTfj4IJw9hPxbQxjceOeOufe6ikY_1ZwndJaaP3Rh3DI6BwzazcTxrh7Y0l42O4WrFRg86QA1xi83jY_SFup20h933Xdy2Cox0LuzR4kU
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJQUzI1NiJ9.IiI.HlJaOfS2PMi4mWzE8-0EgXt06-MeqzaLRy_04gs4HTS7FugbSJ0rJiwUwhss6O1KWT9TvDqo6AQBO_2hV1DKDiBIIh5Z6M92uC4MJNVLbAVQo6dSBt2DfSzioBI5MoDOBvgbIwSZAIFMqKTbYDa9rQ3XRAaClpqrIN-ACa3gz99ds5mYvUyiYsL5uuEBuWrp8DRk6WKjduhpOi4sMvylZbnfop1uHbvg6_dk5lzXt-1MKIW1QJW_63cFn7vdap5T9U4DBsEkCzYtuwgU-UCmsC8W07QEfcrJhHIlYoPQPHePKF0A4dVHKrgRmf1ik2p6e-VNw129JMvx0KO6v_JBww
eyJhbGciOiJQUzI1NiJ9.IiI.cG5_Q1ghrgjQ8gr8Zv7QJB0c-zK3kcoJ1uCn20BdI-1c8ixqpCHIq4xa-m04E84H5lN8jpWzbEl0XAf1c56n2DBGG8SgK9K5UgwajNEEiOzUXu7pXHq-6flPJ6KXK0NeSDtLFxNEfEzKkgJflMMHOXpBfkYKCvgmQlPHkcVO19id1_Yeq5L-POyeTjxlma2WyUliBzHOx2UXnu7wkj_K0a-sfRXhqV64bN-ywpC90x_enTer1Dur3PHDZnlmw5TGrxkg2Mpm_3gcrYv4SFAEE7QA1R9WFFDQt21c5kr-v9TMDg8LSRTGk7pGcMkgoREsywIoK3qZYzMmYs0mmG1ApA
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJQUzM4NCJ9.IiI.AHBo1kZW72IQfs7NvjfrD_WpDa9avLdKyf_rqcCp0mJtGID60cgOG5RDTmI6K7TwzykW6l6LjEuYXDR8hemri6mQrtpQ6rMVTJwqJ6D8M92vH4b2gDBwSwbKz427bGdd_fnqm5K2ntwZGC7pceYg1zbcUQ6NJXs3vqKI6YSKustmm9yA1iMfugFG4eLAPrpfTtLmT1sSWYTYWHVT-6G5q7Bfk7Yu5aHiGDQTo427-Y9YF2fabIuDyCGG48UrBp0ajlm1MHKCBuOvK6NI5Jojd9IWDIf7tvAArsrKVR8QRvDXqqPInJEEZ5x7H1YEEZ5Qrh4XKVhRh9b3O-grDMxMng
eyJhbGciOiJQUzM4NCJ9.IiI.rDDCp3s3RQQGM0MVSclGp9Rv4Ngc87cF7z5NY8g-Mp60D_PcRoJ0M1mBmLR_O1s1kheNyyFiQvZY-N1vM2hXPXBLdzCmMjog69W9iWRyzAh4BTFO9DKoYw1ERZXN13UDQ0RdM_TQlDGo_Prk6LOn15E4Xz6uBbaum7YaHN99T5Ilj12OvDQ8bkUqEk9wgMPVWOdP-iEsdpFd2M3poE-VYLV6qIQ9B2jWOq56_wAS2cB-rCMJsL-4Ev_SrZAVjnc73GIvB75Sx5I9NexdGWzJh9wyJWw60J9cl178Ny2jVSHg-m8x2u8do8I0ObO0-27-cbcrVfn10hIjJpSNpNB1hg
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJQUzUxMiJ9.IiI.o_-UDhc26qYAstuaFJQUz8OKw3UeMc4N7b3U4qcLM-84dxRdw-wBw1rf94jX71vsrFQ2bEh6J5fc4_VtYgKBb2P6QvoL55c7Gqr-5JBw8BkoiiCzlvKIsi_j41FH5Gb4ZBE5Nf9vZD7DnD9BhYXadxaiksx20oNRKIKQ3oMiJxH1w0c-miCSoIR0jnS1QLlKoHYVb7wnkCiR2SOYQ42Je8B8REVzWm2GrqS2cRWnpi3nHihrapruL_BA161Ip1uH4lUFdZLXeG-R6pAlg1OJ_QXSZlP16nzT6MAW_-IFXfioR1QKT8AFNBodY8zlQCGglMyppZi5Y9i7YaMxFgnM4A
eyJhbGciOiJQUzUxMiJ9.IiI.H-pMk9Ig2jCvM2eJnmclfN4V4fwQZO8kQKilXfNxJC2R-q1QbRv0iK6OU5uJk6zO03jc9s86GwHg_hkoT68oszC--ca83hSOQ3KAzF5YukrRuQbskbz3SZAvdjXNAd29JlGAAGc0tl86ghBrNkLLkhEDKAlHGMZqZXSUmAMecCgpu9IN6vXOdaqDOdyYR7BRmEm8sSnAvYVwxDCSdSYq7Yn0Dc3c5SlzjgF0UEEihy9dGmBVDVcMC3II9DOdSBghEyokjWXVSr423nosOd_XWO_TqcTjLo4evdwmNIhgyj1KtQ8YQfrMLisxk8570NSQSEzzRRk1st9zOS3zPlbY2A
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJSUzI1NiJ9.IiI.H_iz_ry505dPMNxQIi4raU88i3wu7DS0Rre6Qm_LJz0Ee_gd5C_t92fBcrFkber1XL_p8AvlXx4DT2Zr_PMBL_2IblJ7t0Od5wnGC__twarj0v1t6KfUkLXcJ3Jy-StnHNbFTmdFnLuGGWIO7xG9h6xgKIvTroVoLJekMzYCc0wSFiyCfaow4yuKesQHUO-N9VDDPoYhkCPqbhVI_d0y6u7KmQy97FbCdCIxvPGHWrwxWcmYbTh4K9xhGDspDUUEubjYTg3t-oaMc2TJqWvu2FE8jyD02A8OCgca6bCU3NmV_Qr6LSUpFNsL4c-0sIp3-L9ndEWzGnN-ZeeGKur-FQ
eyJhbGciOiJSUzI1NiJ9.IiI.gq_hQ6VcQNMVmKlQltK5pS_Yu8PoTCFoWHqQVj1VymYymuKJ9GSgPDxgtkPQVotB985ZaNCuLjoXA4x-xVgMTroSdTQiupBDPpzhZhOuHPgKFQzmC8aBkWxAF_xxLBlZOMwiSly6k_0afE5GgY1SnHu9I57TkGLwHQnTOvL-ED7LvkZxTefxxsDMjgZjboNEPEjbkHl859we5_nKMeL_8jUAhijvaksWZK8pNQdeqg9V9ZNHOgtUG1pPwlSYMjrOTk_a1y6yXAihvuZCwbCCiuquiPi1oWI9Nfv5YGeT8SjSDHAYYJTRyaNOo62fwFC-BuYjVDBdl3uZtO-Ys2g8CA
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJSUzM4NCJ9.IiI.bxKYTQQ4RlxOUvxbU_kuwJKGXXiuIPeRgO78a_3zHjvxIzDNKDvQK3w4DUVTlibR-iTVOASRSycWifBJZx_tsU7-BSqrBcjMtgP7mW-HwZ6pANO071iPkkiQU7gqMzbc2tz4uqGI0Z0izkX0_9dOOFSb7jKIUMzzW1O14fBPhZ4kPqkj07A9S9LW9lauQUTXrFgyEaT6G372cyNxi3-T55u9lkjjiiVN4TAhkaXUSN79IE2rNstU8DtKKs725WNUFy30f1-Ftc-J2uGEOsMZ9CQvEVPwOKbvFY2Uh1S8-FT4ahhwj1fxrmUwDH2lSmz6Rj5zf9-FF-IzivSVq4Z4ig
eyJhbGciOiJSUzM4NCJ9.IiI.KXWxSvxoLuCwtpP-N0fCAFho6zFI44P-42ALMx70vQiM9C_MKbLGpmSET_-GJIQ-fjxJ8jpFmVQjfKuhzHpJZP6JVTHVFg34Z0KOKYM45QqLPooXOf7c9O46DczFoJC0mGuMAWsAtEvgvFgRYHe8KgPg_HBczcHZ71uYDLyz5BINqG_TaDRQBT5vNoPKrnP526CJrHHNT-h2XJumhOjC1XVDj8lj1hlWk63xepZ7fybhLIDAKuEgjfTLBkAaJ1V2hz46uD7g_vvGXGEiBDW93_zWKoTs9ZDrBt-kL82GGay3zLTRHFRORah4hI4GbnJHgy22Dj-RhTJm3deTejkSjg
@@ -2,4 +2,4 @@
source: crates/keystore/tests/keystore.rs
expression: token.as_str()
---
eyJhbGciOiJSUzUxMiJ9.IiI.nFsZ3X8GCgpPEojuEktc9a4C-YGQYx8XpbzhOkgnMVrw_wpqIQgWI--4r6BYV6TYAH8NBdQ8Dkdw6POh1Ni-vAtE2rAzjU19ySth5mfP7WEJXRxA1oEV3-dOqCgUI2JJEM13DuLlWFsUaOCbc1_kCkiziTcLtNap__EPGp5koRy-ZyVa1p_mQSQ4NlhJ3hZfHMGnQ0k3RWnpBn3AqERWllQllLniWGQ4l7rZStsD8PRr-rg7P7W7CRIyjrDqy_3bNJyKQCzs_oUrxO-Z7CU6-KfAeyM2U80TQvhZb-Z8_1dJ8e9WsfudQMLtHgO4tlD678Ywezjvr5ackZdn4QEEEA
eyJhbGciOiJSUzUxMiJ9.IiI.AwxfqjEihH6xYO8xNF24sg5cO8z2bS50V-27YQEViePcRlaqPZHXn6h45YxFXbElrXgKtM97y0KXa8Rr5TrfyH8VXB1OzHNyQ76cZ4zbfYveMZhBh7pGiHVMEPQ0ZErobZXyk9Rxe-HxK1zi9qmmJZLHsQLEFh5zDkTg5dgpEJcklxmCTCT0RLDcilsNdaL7XkTMyjmMck25xciteEy3mpGXppRuDQwsN4ywfNp9VDBC5NjxBYF39D7hkvybOF5eKeaXVo2zw9OmJ4wNg_KgQdNAf-y8wgU71ydo5FHa8d9--HZFTn9ifxZYOCXd34k5vKyScdaXTLUtGFlt0zjDxA
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -25,8 +26,8 @@ use oauth2_types::{
scope::{OPENID, Scope},
};
use rand::{
Rng,
distributions::{Alphanumeric, DistString},
RngExt,
distr::{Alphanumeric, SampleString},
};
use serde::Serialize;
use url::Url;
@@ -214,7 +215,7 @@ struct FullAuthorizationRequest {
/// Build the authorization request.
fn build_authorization_request(
authorization_data: AuthorizationRequestData,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<(FullAuthorizationRequest, AuthorizationValidationData), AuthorizationError> {
let AuthorizationRequestData {
client_id,
@@ -327,7 +328,7 @@ fn build_authorization_request(
pub fn build_authorization_url(
authorization_endpoint: Url,
authorization_data: AuthorizationRequestData,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<(Url, AuthorizationValidationData), AuthorizationError> {
tracing::debug!(
scope = ?authorization_data.scope,
@@ -403,7 +404,7 @@ pub async fn access_token_with_authorization_code(
validation_data: AuthorizationValidationData,
id_token_verification_data: Option<JwtVerificationData<'_>>,
now: DateTime<Utc>,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<(AccessTokenResponse, Option<IdToken<'static>>), TokenAuthorizationCodeError> {
tracing::debug!("Exchanging authorization code for access token...");
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -13,7 +14,7 @@ use oauth2_types::{
requests::{AccessTokenRequest, AccessTokenResponse, ClientCredentialsGrant},
scope::Scope,
};
use rand::Rng;
use rand::RngExt;
use url::Url;
use crate::{
@@ -51,7 +52,7 @@ pub async fn access_token_with_client_credentials(
token_endpoint: &Url,
scope: Option<Scope>,
now: DateTime<Utc>,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<AccessTokenResponse, TokenRequestError> {
tracing::debug!("Requesting access token with client credentials...");
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -14,7 +15,7 @@ use oauth2_types::{
requests::{AccessTokenRequest, AccessTokenResponse, RefreshTokenGrant},
scope::Scope,
};
use rand::Rng;
use rand::RngExt;
use url::Url;
use super::jose::JwtVerificationData;
@@ -75,7 +76,7 @@ pub async fn refresh_access_token(
id_token_verification_data: Option<JwtVerificationData<'_>>,
auth_id_token: Option<&IdToken<'_>>,
now: DateTime<Utc>,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<(AccessTokenResponse, Option<IdToken<'static>>), TokenRefreshError> {
tracing::debug!("Refreshing access token…");
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -11,7 +12,7 @@ use http::header::ACCEPT;
use mas_http::RequestBuilderExt;
use mime::APPLICATION_JSON;
use oauth2_types::requests::{AccessTokenRequest, AccessTokenResponse};
use rand::Rng;
use rand::RngExt;
use url::Url;
use crate::{
@@ -46,7 +47,7 @@ pub async fn request_access_token(
token_endpoint: &Url,
request: AccessTokenRequest,
now: DateTime<Utc>,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<AccessTokenResponse, TokenRequestError> {
tracing::debug!(?request, "Requesting access token...");
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -18,7 +19,7 @@ use mas_jose::{
jwt::{JsonWebSignatureHeader, Jwt},
};
use mas_keystore::Keystore;
use rand::Rng;
use rand::RngExt;
use serde::Serialize;
use serde_json::Value;
use url::Url;
@@ -135,7 +136,7 @@ impl ClientCredentials {
request: reqwest::RequestBuilder,
form: &T,
now: DateTime<Utc>,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<reqwest::RequestBuilder, CredentialsError> {
let request = match self {
ClientCredentials::None { client_id } => request.form(&RequestWithClientCredentials {
@@ -331,7 +332,7 @@ fn prepare_claims(
iss: String,
aud: String,
now: DateTime<Utc>,
rng: &mut impl Rng,
rng: &mut impl RngExt,
) -> Result<HashMap<String, Value>, ClaimError> {
let mut claims = HashMap::new();
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 Kévin Commaille.
//
@@ -19,7 +20,7 @@ use mas_keystore::{JsonWebKey, JsonWebKeySet, Keystore, PrivateKey};
use mas_oidc_client::types::{IdToken, client_credentials::ClientCredentials};
use rand::{
SeedableRng,
distributions::{Alphanumeric, DistString},
distr::{Alphanumeric, SampleString},
};
use url::Url;
use wiremock::MockServer;
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -8,7 +9,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Duration, Utc};
use mas_data_model::{Clock, CompatAccessToken, CompatSession, UlidExt as _};
use mas_storage::compat::CompatAccessTokenRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -136,7 +137,7 @@ impl CompatAccessTokenRepository for PgCompatAccessTokenRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
compat_session: &CompatSession,
token: String,
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -11,7 +12,7 @@ use mas_data_model::{
UlidExt as _,
};
use mas_storage::compat::CompatRefreshTokenRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -148,7 +149,7 @@ impl CompatRefreshTokenRepository for PgCompatRefreshTokenRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
compat_session: &CompatSession,
compat_access_token: &CompatAccessToken,
+2 -2
View File
@@ -18,7 +18,7 @@ use mas_storage::{
compat::{CompatSessionFilter, CompatSessionRepository},
pagination::Node,
};
use rand::RngCore;
use rand::Rng;
use sea_query::{Expr, ExprTrait, PostgresQueryBuilder, Query, enum_def};
use sea_query_sqlx::SqlxBinder;
use sqlx::PgConnection;
@@ -337,7 +337,7 @@ impl CompatSessionRepository for PgCompatSessionRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
device: Device,
+2 -2
View File
@@ -15,7 +15,7 @@ use mas_storage::{
compat::{CompatSsoLoginFilter, CompatSsoLoginRepository},
pagination::Node,
};
use rand::RngCore;
use rand::Rng;
use sea_query::{Expr, ExprTrait, PostgresQueryBuilder, Query, enum_def};
use sea_query_sqlx::SqlxBinder;
use sqlx::PgConnection;
@@ -274,7 +274,7 @@ impl CompatSsoLoginRepository for PgCompatSsoLoginRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
login_token: String,
redirect_uri: Url,
+3 -3
View File
@@ -22,7 +22,7 @@
//! ```rust
//! # use async_trait::async_trait;
//! # use ulid::Ulid;
//! # use rand::RngCore;
//! # use rand::Rng;
//! # use mas_data_model::Clock;
//! # use mas_data_model::UlidExt;
//! # use mas_storage_pg::{DatabaseError, ExecuteExt};
@@ -42,7 +42,7 @@
//! # async fn lookup(&mut self, id: Ulid) -> Result<Option<FakeData>, Self::Error>;
//! # async fn add(
//! # &mut self,
//! # rng: &mut (dyn RngCore + Send),
//! # rng: &mut (dyn Rng + Send),
//! # clock: &dyn Clock,
//! # ) -> Result<FakeData, Self::Error>;
//! # }
@@ -116,7 +116,7 @@
//! )]
//! async fn add(
//! &mut self,
//! rng: &mut (dyn RngCore + Send),
//! rng: &mut (dyn Rng + Send),
//! clock: &dyn Clock,
//! ) -> Result<FakeData, Self::Error> {
//! let created_at = clock.now();
+2 -2
View File
@@ -9,7 +9,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Duration, Utc};
use mas_data_model::{AccessToken, AccessTokenState, Clock, Session, UlidExt as _};
use mas_storage::oauth2::OAuth2AccessTokenRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -139,7 +139,7 @@ impl OAuth2AccessTokenRepository for PgOAuth2AccessTokenRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &Session,
access_token: String,
@@ -16,7 +16,7 @@ use mas_data_model::{
use mas_iana::oauth::PkceCodeChallengeMethod;
use mas_storage::oauth2::OAuth2AuthorizationGrantRepository;
use oauth2_types::{requests::ResponseMode, scope::Scope};
use rand::RngCore;
use rand::Rng;
use sqlx::{PgConnection, types::Json};
use ulid::Ulid;
use url::Url;
@@ -200,7 +200,7 @@ impl OAuth2AuthorizationGrantRepository for PgOAuth2AuthorizationGrantRepository
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
redirect_uri: Url,
+2 -2
View File
@@ -21,7 +21,7 @@ use mas_storage::{
};
use oauth2_types::{oidc::ApplicationType, requests::GrantType};
use opentelemetry_semantic_conventions::attribute::DB_QUERY_TEXT;
use rand::RngCore;
use rand::Rng;
use sea_query::{
Expr, ExprTrait, PostgresQueryBuilder, Query, SimpleExpr, enum_def,
extension::postgres::PgExpr as _,
@@ -492,7 +492,7 @@ impl OAuth2ClientRepository for PgOAuth2ClientRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
redirect_uris: Vec<Url>,
metadata_digest: Option<String>,
@@ -14,7 +14,7 @@ use mas_data_model::{
};
use mas_storage::oauth2::{OAuth2DeviceCodeGrantParams, OAuth2DeviceCodeGrantRepository};
use oauth2_types::scope::Scope;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -157,7 +157,7 @@ impl OAuth2DeviceCodeGrantRepository for PgOAuth2DeviceCodeGrantRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
params: OAuth2DeviceCodeGrantParams<'_>,
) -> Result<DeviceCodeGrant, Self::Error> {
@@ -9,7 +9,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Utc};
use mas_data_model::{AccessToken, Clock, RefreshToken, RefreshTokenState, Session, UlidExt as _};
use mas_storage::oauth2::OAuth2RefreshTokenRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -170,7 +170,7 @@ impl OAuth2RefreshTokenRepository for PgOAuth2RefreshTokenRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &Session,
access_token: &AccessToken,
+2 -2
View File
@@ -16,7 +16,7 @@ use mas_storage::{
pagination::Node,
};
use oauth2_types::scope::{Scope, ScopeToken};
use rand::RngCore;
use rand::Rng;
use sea_query::{
Condition, Expr, ExprTrait, PgFunc, PostgresQueryBuilder, Query, SimpleExpr, enum_def,
extension::postgres::PgExpr,
@@ -272,7 +272,7 @@ impl OAuth2SessionRepository for PgOAuth2SessionRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
user: Option<&User>,
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -10,7 +11,7 @@ use mas_data_model::{
personal::{PersonalAccessToken, session::PersonalSession},
};
use mas_storage::personal::PersonalAccessTokenRepository;
use rand::RngCore;
use rand::Rng;
use sha2::{Digest, Sha256};
use sqlx::PgConnection;
use ulid::Ulid;
@@ -177,7 +178,7 @@ impl PersonalAccessTokenRepository for PgPersonalAccessTokenRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &PersonalSession,
access_token: &str,
+2 -2
View File
@@ -22,7 +22,7 @@ use mas_storage::{
};
use oauth2_types::scope::Scope;
use opentelemetry_semantic_conventions::trace::DB_QUERY_TEXT;
use rand::RngCore;
use rand::Rng;
use sea_query::{
Cond, Condition, Expr, ExprTrait, PgFunc, PostgresQueryBuilder, Query, SimpleExpr, enum_def,
extension::postgres::PgExpr as _,
@@ -243,7 +243,7 @@ impl PersonalSessionRepository for PgPersonalSessionRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
owner: PersonalSessionOwner,
actor_user: &User,
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -9,7 +10,7 @@
use async_trait::async_trait;
use mas_data_model::{Clock, PolicyData, UlidExt as _};
use mas_storage::policy_data::PolicyDataRepository;
use rand::RngCore;
use rand::Rng;
use serde_json::Value;
use sqlx::{PgConnection, types::Json};
use ulid::Ulid;
@@ -90,7 +91,7 @@ impl PolicyDataRepository for PgPolicyDataRepository<'_> {
)]
async fn set(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
data: Value,
) -> Result<PolicyData, Self::Error> {
+4 -4
View File
@@ -12,7 +12,7 @@ use chrono::{DateTime, Duration, Utc};
use mas_data_model::{Clock, UlidExt as _};
use mas_storage::queue::{Job, QueueJobRepository, Worker};
use opentelemetry_semantic_conventions::trace::DB_QUERY_TEXT;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use tracing::Instrument;
use ulid::Ulid;
@@ -90,7 +90,7 @@ impl QueueJobRepository for PgQueueJobRepository<'_> {
)]
async fn schedule(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
queue_name: &str,
payload: serde_json::Value,
@@ -132,7 +132,7 @@ impl QueueJobRepository for PgQueueJobRepository<'_> {
)]
async fn schedule_later(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
queue_name: &str,
payload: serde_json::Value,
@@ -335,7 +335,7 @@ impl QueueJobRepository for PgQueueJobRepository<'_> {
)]
async fn retry(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
id: Ulid,
delay: Duration,
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -10,7 +11,7 @@ use async_trait::async_trait;
use chrono::Duration;
use mas_data_model::{Clock, UlidExt as _};
use mas_storage::queue::{QueueWorkerRepository, Worker};
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -46,7 +47,7 @@ impl QueueWorkerRepository for PgQueueWorkerRepository<'_> {
)]
async fn register(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
) -> Result<Worker, Self::Error> {
let now = clock.now();
@@ -14,7 +14,7 @@ use mas_storage::{
upstream_oauth2::{UpstreamOAuthLinkFilter, UpstreamOAuthLinkRepository},
};
use opentelemetry_semantic_conventions::trace::DB_QUERY_TEXT;
use rand::RngCore;
use rand::Rng;
use sea_query::{
Expr, ExprTrait, PostgresQueryBuilder, Query, enum_def, extension::postgres::PgExpr as _,
};
@@ -221,7 +221,7 @@ impl UpstreamOAuthLinkRepository for PgUpstreamOAuthLinkRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
upstream_oauth_provider: &UpstreamOAuthProvider,
subject: String,
@@ -18,7 +18,7 @@ use mas_storage::{
},
};
use opentelemetry_semantic_conventions::attribute::DB_QUERY_TEXT;
use rand::RngCore;
use rand::Rng;
use sea_query::{Expr, ExprTrait, PostgresQueryBuilder, Query, enum_def};
use sea_query_sqlx::SqlxBinder;
use sqlx::{PgConnection, types::Json};
@@ -330,7 +330,7 @@ impl UpstreamOAuthProviderRepository for PgUpstreamOAuthProviderRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
params: UpstreamOAuthProviderParams,
) -> Result<UpstreamOAuthProvider, Self::Error> {
@@ -16,7 +16,7 @@ use mas_storage::{
pagination::Node,
upstream_oauth2::{UpstreamOAuthSessionFilter, UpstreamOAuthSessionRepository},
};
use rand::RngCore;
use rand::Rng;
use sea_query::{
Expr, ExprTrait, PostgresQueryBuilder, Query, enum_def, extension::postgres::PgExpr,
};
@@ -253,7 +253,7 @@ impl UpstreamOAuthSessionRepository for PgUpstreamOAuthSessionRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
upstream_oauth_provider: &UpstreamOAuthProvider,
state_str: String,
+5 -5
View File
@@ -16,7 +16,7 @@ use mas_storage::{
pagination::Node,
user::{UserEmailFilter, UserEmailRepository},
};
use rand::RngCore;
use rand::Rng;
use sea_query::{Expr, ExprTrait, Func, PostgresQueryBuilder, Query, SimpleExpr, enum_def};
use sea_query_sqlx::SqlxBinder;
use sqlx::PgConnection;
@@ -354,7 +354,7 @@ impl UserEmailRepository for PgUserEmailRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
email: String,
@@ -448,7 +448,7 @@ impl UserEmailRepository for PgUserEmailRepository<'_> {
)]
async fn add_authentication_for_session(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
email: String,
session: &BrowserSession,
@@ -500,7 +500,7 @@ impl UserEmailRepository for PgUserEmailRepository<'_> {
)]
async fn add_authentication_for_registration(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
email: String,
user_registration: &UserRegistration,
@@ -553,7 +553,7 @@ impl UserEmailRepository for PgUserEmailRepository<'_> {
)]
async fn add_authentication_code(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
duration: chrono::Duration,
user_email_authentication: &UserEmailAuthentication,
+2 -2
View File
@@ -11,7 +11,7 @@
use async_trait::async_trait;
use mas_data_model::{Clock, UlidExt as _, User};
use mas_storage::user::{UserFilter, UserRepository};
use rand::RngCore;
use rand::Rng;
use sea_query::{
Expr, ExprTrait, PostgresQueryBuilder, Query, SimpleExpr, extension::postgres::PgExpr as _,
};
@@ -295,7 +295,7 @@ impl UserRepository for PgUserRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
username: String,
) -> Result<User, Self::Error> {
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -8,7 +9,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Utc};
use mas_data_model::{Clock, Password, UlidExt as _, User};
use mas_storage::user::UserPasswordRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -108,7 +109,7 @@ impl UserPasswordRepository for PgUserPasswordRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
version: u16,
+3 -3
View File
@@ -11,7 +11,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Duration, Utc};
use mas_data_model::{Clock, UlidExt as _, UserEmail, UserRecoverySession, UserRecoveryTicket};
use mas_storage::user::UserRecoveryRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -134,7 +134,7 @@ impl UserRecoveryRepository for PgUserRecoveryRepository<'_> {
)]
async fn add_session(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
email: String,
user_agent: String,
@@ -232,7 +232,7 @@ impl UserRecoveryRepository for PgUserRecoveryRepository<'_> {
)]
async fn add_ticket(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user_recovery_session: &UserRecoverySession,
user_email: &UserEmail,
+2 -2
View File
@@ -13,7 +13,7 @@ use mas_data_model::{
UserRegistration, UserRegistrationPassword, UserRegistrationToken,
};
use mas_storage::user::UserRegistrationRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use url::Url;
@@ -167,7 +167,7 @@ impl UserRegistrationRepository for PgUserRegistrationRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
username: String,
ip_address: Option<IpAddr>,
@@ -12,7 +12,7 @@ use mas_storage::{
pagination::Node,
user::{UserRegistrationTokenFilter, UserRegistrationTokenRepository},
};
use rand::RngCore;
use rand::Rng;
use sea_query::{Condition, Expr, ExprTrait, PostgresQueryBuilder, Query, enum_def};
use sea_query_sqlx::SqlxBinder;
use sqlx::PgConnection;
@@ -435,7 +435,7 @@ impl UserRegistrationTokenRepository for PgUserRegistrationTokenRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn mas_data_model::Clock,
token: String,
usage_limit: Option<u32>,
+4 -4
View File
@@ -18,7 +18,7 @@ use mas_storage::{
pagination::Node,
user::{BrowserSessionFilter, BrowserSessionRepository},
};
use rand::RngCore;
use rand::Rng;
use sea_query::{Expr, ExprTrait, PostgresQueryBuilder, Query};
use sea_query_sqlx::SqlxBinder;
use sqlx::PgConnection;
@@ -240,7 +240,7 @@ impl BrowserSessionRepository for PgBrowserSessionRepository<'_> {
)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
user_agent: Option<String>,
@@ -469,7 +469,7 @@ impl BrowserSessionRepository for PgBrowserSessionRepository<'_> {
)]
async fn authenticate_with_password(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user_session: &BrowserSession,
user_password: &Password,
@@ -518,7 +518,7 @@ impl BrowserSessionRepository for PgBrowserSessionRepository<'_> {
)]
async fn authenticate_with_upstream(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user_session: &BrowserSession,
upstream_oauth_session: &UpstreamOAuthAuthorizationSession,
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2024 The Matrix.org Foundation C.I.C.
//
@@ -7,7 +8,7 @@
use async_trait::async_trait;
use mas_data_model::{Clock, UlidExt as _, User};
use mas_storage::user::UserTermsRepository;
use rand::RngCore;
use rand::Rng;
use sqlx::PgConnection;
use ulid::Ulid;
use url::Url;
@@ -45,7 +46,7 @@ impl UserTermsRepository for PgUserTermsRepository<'_> {
)]
async fn accept_terms(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
terms_url: Url,
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -7,7 +8,7 @@
use async_trait::async_trait;
use chrono::Duration;
use mas_data_model::{Clock, CompatAccessToken, CompatSession};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::repository_impl;
@@ -66,7 +67,7 @@ pub trait CompatAccessTokenRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
compat_session: &CompatSession,
token: String,
@@ -98,7 +99,7 @@ repository_impl!(CompatAccessTokenRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
compat_session: &CompatSession,
token: String,
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -6,7 +7,7 @@
use async_trait::async_trait;
use mas_data_model::{Clock, CompatAccessToken, CompatRefreshToken, CompatSession};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::repository_impl;
@@ -62,7 +63,7 @@ pub trait CompatRefreshTokenRepository: Send + Sync {
/// * `token`: The token of the refresh token
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
compat_session: &CompatSession,
compat_access_token: &CompatAccessToken,
@@ -114,7 +115,7 @@ repository_impl!(CompatRefreshTokenRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
compat_session: &CompatSession,
compat_access_token: &CompatAccessToken,
+3 -3
View File
@@ -10,7 +10,7 @@ use std::net::IpAddr;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use mas_data_model::{BrowserSession, Clock, CompatSession, CompatSsoLogin, Device, User};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::{Page, Pagination, repository_impl, user::BrowserSessionFilter};
@@ -274,7 +274,7 @@ pub trait CompatSessionRepository: Send + Sync {
#[expect(clippy::too_many_arguments)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
device: Device,
@@ -449,7 +449,7 @@ repository_impl!(CompatSessionRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
user: &User,
device: Device,
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -6,7 +7,7 @@
use async_trait::async_trait;
use mas_data_model::{BrowserSession, Clock, CompatSession, CompatSsoLogin, User};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use url::Url;
@@ -162,7 +163,7 @@ pub trait CompatSsoLoginRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
login_token: String,
redirect_uri: Url,
@@ -255,7 +256,7 @@ repository_impl!(CompatSsoLoginRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
login_token: String,
redirect_uri: Url,
+3 -2
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -58,7 +59,7 @@
//! /// Returns [`Self::Error`] if the underlying repository fails
//! async fn add(
//! &mut self,
//! rng: &mut (dyn RngCore + Send),
//! rng: &mut (dyn Rng + Send),
//! clock: &dyn Clock,
//! ) -> Result<FakeData, Self::Error>;
//! }
@@ -67,7 +68,7 @@
//! async fn lookup(&mut self, id: Ulid) -> Result<Option<FakeData>, Self::Error>;
//! async fn add(
//! &mut self,
//! rng: &mut (dyn RngCore + Send),
//! rng: &mut (dyn Rng + Send),
//! clock: &dyn Clock,
//! ) -> Result<FakeData, Self::Error>;
//! );
+3 -3
View File
@@ -8,7 +8,7 @@
use async_trait::async_trait;
use chrono::{DateTime, Duration, Utc};
use mas_data_model::{AccessToken, Clock, Session};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::repository_impl;
@@ -67,7 +67,7 @@ pub trait OAuth2AccessTokenRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &Session,
access_token: String,
@@ -163,7 +163,7 @@ repository_impl!(OAuth2AccessTokenRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &Session,
access_token: String,
@@ -12,7 +12,7 @@ use mas_data_model::{
AuthorizationCode, AuthorizationGrant, BrowserSession, Client, Clock, Session,
};
use oauth2_types::{requests::ResponseMode, scope::Scope};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use url::Url;
@@ -56,7 +56,7 @@ pub trait OAuth2AuthorizationGrantRepository: Send + Sync {
#[expect(clippy::too_many_arguments)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
redirect_uri: Url,
@@ -167,7 +167,7 @@ pub trait OAuth2AuthorizationGrantRepository: Send + Sync {
repository_impl!(OAuth2AuthorizationGrantRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
redirect_uri: Url,
+3 -3
View File
@@ -12,7 +12,7 @@ use mas_data_model::{Client, Clock};
use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod};
use mas_jose::jwk::PublicJsonWebKeySet;
use oauth2_types::{oidc::ApplicationType, requests::GrantType};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use url::Url;
@@ -232,7 +232,7 @@ pub trait OAuth2ClientRepository: Send + Sync {
#[expect(clippy::too_many_arguments)]
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
redirect_uris: Vec<Url>,
metadata_digest: Option<String>,
@@ -360,7 +360,7 @@ repository_impl!(OAuth2ClientRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
redirect_uris: Vec<Url>,
metadata_digest: Option<String>,
@@ -11,7 +11,7 @@ use async_trait::async_trait;
use chrono::Duration;
use mas_data_model::{BrowserSession, Client, Clock, DeviceCodeGrant, Session};
use oauth2_types::scope::Scope;
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::repository_impl;
@@ -63,7 +63,7 @@ pub trait OAuth2DeviceCodeGrantRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
params: OAuth2DeviceCodeGrantParams<'_>,
) -> Result<DeviceCodeGrant, Self::Error>;
@@ -216,7 +216,7 @@ pub trait OAuth2DeviceCodeGrantRepository: Send + Sync {
repository_impl!(OAuth2DeviceCodeGrantRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
params: OAuth2DeviceCodeGrantParams<'_>,
) -> Result<DeviceCodeGrant, Self::Error>;
+3 -3
View File
@@ -7,7 +7,7 @@
use async_trait::async_trait;
use mas_data_model::{AccessToken, Clock, RefreshToken, Session};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::repository_impl;
@@ -66,7 +66,7 @@ pub trait OAuth2RefreshTokenRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &Session,
access_token: &AccessToken,
@@ -170,7 +170,7 @@ repository_impl!(OAuth2RefreshTokenRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &Session,
access_token: &AccessToken,
+7 -7
View File
@@ -11,7 +11,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Utc};
use mas_data_model::{BrowserSession, Client, Clock, Device, Session, User};
use oauth2_types::scope::Scope;
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::{Pagination, pagination::Page, repository_impl, user::BrowserSessionFilter};
@@ -348,7 +348,7 @@ pub trait OAuth2SessionRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
user: Option<&User>,
@@ -374,7 +374,7 @@ pub trait OAuth2SessionRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add_from_browser_session(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
user_session: &BrowserSession,
@@ -408,7 +408,7 @@ pub trait OAuth2SessionRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add_from_client_credentials(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
scope: Scope,
@@ -568,7 +568,7 @@ repository_impl!(OAuth2SessionRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
user: Option<&User>,
@@ -578,7 +578,7 @@ repository_impl!(OAuth2SessionRepository:
async fn add_from_browser_session(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
user_session: &BrowserSession,
@@ -587,7 +587,7 @@ repository_impl!(OAuth2SessionRepository:
async fn add_from_client_credentials(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
client: &Client,
scope: Scope,
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -9,7 +10,7 @@ use mas_data_model::{
Clock,
personal::{PersonalAccessToken, session::PersonalSession},
};
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::repository_impl;
@@ -84,7 +85,7 @@ pub trait PersonalAccessTokenRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &PersonalSession,
access_token: &str,
@@ -125,7 +126,7 @@ repository_impl!(PersonalAccessTokenRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
session: &PersonalSession,
access_token: &str,
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -15,7 +16,7 @@ use mas_data_model::{
},
};
use oauth2_types::scope::Scope;
use rand_core::RngCore;
use rand_core::Rng;
use ulid::Ulid;
use crate::{Page, Pagination, repository_impl};
@@ -61,7 +62,7 @@ pub trait PersonalSessionRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
owner: PersonalSessionOwner,
actor_user: &User,
@@ -154,7 +155,7 @@ repository_impl!(PersonalSessionRepository:
async fn add(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
owner: PersonalSessionOwner,
actor_user: &User,
+4 -3
View File
@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
@@ -7,7 +8,7 @@
use async_trait::async_trait;
use mas_data_model::{Clock, PolicyData};
use rand_core::RngCore;
use rand_core::Rng;
use crate::repository_impl;
@@ -43,7 +44,7 @@ pub trait PolicyDataRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn set(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
data: serde_json::Value,
) -> Result<PolicyData, Self::Error>;
@@ -67,7 +68,7 @@ repository_impl!(PolicyDataRepository:
async fn set(
&mut self,
rng: &mut (dyn RngCore + Send),
rng: &mut (dyn Rng + Send),
clock: &dyn Clock,
data: serde_json::Value,
) -> Result<PolicyData, Self::Error>;
Loaded 100 of 125 files, more files were not shown because too many files have changed in this diff. Show more