mirror of
https://github.com/signalapp/libsignal.git
synced 2024-09-20 03:52:17 +02:00
Move ServiceId + ProtocolAddress to new libsignal-core crate
...as well as related types Aci, Pni, ServiceId, ServiceIdFixedWidthBinaryBytes, ServiceIdKind, and DeviceId. ...so that zkgroup and libsignal-net don't have to depend on libsignal-protocol (and indirectly on Kyber). The types are still exported from libsignal-protocol, so this is not a source-breaking change. ProtocolAddress is still defined as a (String, DeviceId) pair; a switch to (ServiceId, DeviceId) will probably still happen in the future, but not in this commit.
This commit is contained in:
parent
55b304cc4b
commit
75811b90dc
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -1629,6 +1629,16 @@ dependencies = [
|
||||
"syn-mid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsignal-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal",
|
||||
"num_enum",
|
||||
"proptest",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsignal-ffi"
|
||||
version = "0.36.1"
|
||||
@ -1686,7 +1696,7 @@ dependencies = [
|
||||
"http-body-util",
|
||||
"hyper 1.0.0-rc.4",
|
||||
"lazy_static",
|
||||
"libsignal-protocol",
|
||||
"libsignal-core",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"prost",
|
||||
@ -1744,6 +1754,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"indexmap 1.9.3",
|
||||
"itertools 0.10.5",
|
||||
"libsignal-core",
|
||||
"log",
|
||||
"num_enum",
|
||||
"pqcrypto-kyber 0.7.6",
|
||||
@ -3817,7 +3828,7 @@ dependencies = [
|
||||
"hex-literal",
|
||||
"hkdf",
|
||||
"lazy_static",
|
||||
"libsignal-protocol",
|
||||
"libsignal-core",
|
||||
"partial-default",
|
||||
"poksho",
|
||||
"rand",
|
||||
|
@ -736,6 +736,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<li><a href="https://crates.io/crates/device-transfer">device-transfer 0.1.0</a></li>
|
||||
<li><a href="https://crates.io/crates/libsignal-bridge">libsignal-bridge 0.1.0</a></li>
|
||||
<li><a href="https://crates.io/crates/libsignal-bridge-macros">libsignal-bridge-macros 0.1.0</a></li>
|
||||
<li><a href="https://crates.io/crates/libsignal-core">libsignal-core 0.1.0</a></li>
|
||||
<li><a href="https://crates.io/crates/libsignal-ffi">libsignal-ffi 0.36.1</a></li>
|
||||
<li><a href="https://crates.io/crates/libsignal-jni">libsignal-jni 0.36.1</a></li>
|
||||
<li><a href="https://crates.io/crates/libsignal-net">libsignal-net 0.1.0</a></li>
|
||||
|
@ -669,7 +669,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
|
||||
```
|
||||
|
||||
## attest 0.1.0, device-transfer 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-ffi 0.36.1, libsignal-jni 0.36.1, libsignal-net 0.1.0, libsignal-node 0.36.1, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, poksho 0.7.0, signal-crypto 0.1.0, signal-media 0.1.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, signal-pin 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
|
||||
## attest 0.1.0, device-transfer 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-core 0.1.0, libsignal-ffi 0.36.1, libsignal-jni 0.36.1, libsignal-net 0.1.0, libsignal-node 0.36.1, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, poksho 0.7.0, signal-crypto 0.1.0, signal-media 0.1.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, signal-pin 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
|
||||
|
||||
```
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
|
@ -924,7 +924,7 @@ You should also get your employer (if you work as a programmer) or school, if an
|
||||
<key>License</key>
|
||||
<string>GNU Affero General Public License v3.0</string>
|
||||
<key>Title</key>
|
||||
<string>attest 0.1.0, device-transfer 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-ffi 0.36.1, libsignal-jni 0.36.1, libsignal-net 0.1.0, libsignal-node 0.36.1, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, poksho 0.7.0, signal-crypto 0.1.0, signal-media 0.1.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, signal-pin 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0</string>
|
||||
<string>attest 0.1.0, device-transfer 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-core 0.1.0, libsignal-ffi 0.36.1, libsignal-jni 0.36.1, libsignal-net 0.1.0, libsignal-node 0.36.1, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, poksho 0.7.0, signal-crypto 0.1.0, signal-media 0.1.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, signal-pin 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
|
@ -61,7 +61,7 @@ args = "horizontal"
|
||||
|
||||
[parse]
|
||||
parse_deps = true
|
||||
include = ["libsignal-protocol", "signal-crypto", "signal-pin", "zkgroup", "signal-media", "mediasan-common", "mp4san", "webpsan"]
|
||||
include = ["libsignal-core", "libsignal-protocol", "signal-crypto", "signal-pin", "zkgroup", "signal-media", "mediasan-common", "mp4san", "webpsan"]
|
||||
extra_bindings = ["libsignal-bridge", "zkgroup"]
|
||||
|
||||
[parse.expand]
|
||||
|
19
rust/core/Cargo.toml
Normal file
19
rust/core/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (C) 2023 Signal Messenger, LLC.
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
#
|
||||
|
||||
[package]
|
||||
name = "libsignal-core"
|
||||
version = "0.1.0"
|
||||
authors = ["Signal Messenger LLC"]
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-only"
|
||||
|
||||
[dependencies]
|
||||
num_enum = "0.6.1"
|
||||
uuid = "1.1.2"
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.4.1"
|
||||
proptest = "1.0"
|
@ -9,9 +9,6 @@
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(doc)]
|
||||
use crate::SignalMessage;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Known types of [ServiceId].
|
||||
@ -617,7 +614,7 @@ impl ProtocolAddress {
|
||||
/// all clients for that user.
|
||||
///
|
||||
///```
|
||||
/// use libsignal_protocol::{DeviceId, ProtocolAddress};
|
||||
/// use libsignal_core::{DeviceId, ProtocolAddress};
|
||||
///
|
||||
/// // This is a unique id for some user, typically a UUID.
|
||||
/// let user_id: String = "04899A85-4C9E-44CC-8428-A02AB69335F1".to_string();
|
||||
@ -640,9 +637,9 @@ impl ProtocolAddress {
|
||||
|
||||
/// An identifier representing a particular Signal client instance to send to.
|
||||
///
|
||||
/// For example, if a user has set up Signal on both their phone and laptop, any [SignalMessage]
|
||||
/// sent to the user will still only go to a single device. So when a user sends a message to
|
||||
/// another user at all, they're actually sending a message to *every* device.
|
||||
/// For example, if a user has set up Signal on both their phone and laptop, a particular
|
||||
/// message sent to the user will still only go to a single device. So when a user sends a
|
||||
/// message to another user at all, they're actually sending a message to *every* device.
|
||||
#[inline]
|
||||
pub fn device_id(&self) -> DeviceId {
|
||||
self.device_id
|
9
rust/core/src/lib.rs
Normal file
9
rust/core/src/lib.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright 2023 Signal Messenger, LLC.
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
mod address;
|
||||
pub use address::{
|
||||
Aci, DeviceId, Pni, ProtocolAddress, ServiceId, ServiceIdFixedWidthBinaryBytes, ServiceIdKind,
|
||||
};
|
@ -20,7 +20,7 @@ http = "0.2.9"
|
||||
http-body-util = "0.1.0-rc.3"
|
||||
hyper = { version = "1.0.0-rc.4", features = ["http1", "http2", "client"] }
|
||||
lazy_static = "1.4.0"
|
||||
libsignal-protocol = { path = "../protocol" }
|
||||
libsignal-core = { path = "../core" }
|
||||
log = "0.4.19"
|
||||
pin-project-lite = "0.2.4"
|
||||
prost = "0.12.1"
|
||||
|
@ -16,7 +16,7 @@ use tokio_boring::SslStream;
|
||||
use uuid::Uuid;
|
||||
|
||||
use attest::cds2;
|
||||
use libsignal_protocol::{Aci, Pni};
|
||||
use libsignal_core::{Aci, Pni};
|
||||
|
||||
use crate::infra::connection_manager::ConnectionManager;
|
||||
use crate::infra::errors::NetError;
|
||||
@ -378,8 +378,6 @@ mod test {
|
||||
use hex_literal::hex;
|
||||
use uuid::Uuid;
|
||||
|
||||
use libsignal_protocol::{Aci, Pni};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -11,6 +11,7 @@ edition = "2021"
|
||||
license = "AGPL-3.0-only"
|
||||
|
||||
[dependencies]
|
||||
libsignal-core = { path = "../core" }
|
||||
signal-crypto = { path = "../crypto" }
|
||||
aes = { version = "0.8.3", features = ["zeroize"] }
|
||||
aes-gcm-siv = "0.11.1"
|
||||
|
@ -22,7 +22,6 @@
|
||||
// https://doc.rust-lang.org/rustdoc/what-to-include.html for background.
|
||||
// #![warn(missing_docs)]
|
||||
|
||||
mod address;
|
||||
mod consts;
|
||||
mod crypto;
|
||||
mod curve;
|
||||
@ -45,9 +44,10 @@ mod utils;
|
||||
|
||||
use error::Result;
|
||||
|
||||
pub use address::{
|
||||
pub use libsignal_core::{
|
||||
Aci, DeviceId, Pni, ProtocolAddress, ServiceId, ServiceIdFixedWidthBinaryBytes, ServiceIdKind,
|
||||
};
|
||||
|
||||
pub use curve::{KeyPair, PrivateKey, PublicKey};
|
||||
pub use error::SignalProtocolError;
|
||||
pub use fingerprint::{DisplayableFingerprint, Fingerprint, ScannableFingerprint};
|
||||
|
@ -8,14 +8,13 @@
|
||||
use async_trait::async_trait;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::address::ProtocolAddress;
|
||||
use crate::error::Result;
|
||||
use crate::sender_keys::SenderKeyRecord;
|
||||
use crate::state::{
|
||||
KyberPreKeyId, KyberPreKeyRecord, PreKeyId, PreKeyRecord, SessionRecord, SignedPreKeyId,
|
||||
SignedPreKeyRecord,
|
||||
};
|
||||
use crate::{IdentityKey, IdentityKeyPair};
|
||||
use crate::{IdentityKey, IdentityKeyPair, ProtocolAddress};
|
||||
|
||||
// TODO: consider moving this enum into utils.rs?
|
||||
/// Each Signal message can be considered to have exactly two participants, a sender and receiver.
|
||||
|
@ -12,7 +12,7 @@ description = "A zero-knowledge group library"
|
||||
license = "AGPL-3.0-only"
|
||||
|
||||
[dependencies]
|
||||
libsignal-protocol = { path = "../protocol" }
|
||||
libsignal-core = { path = "../core" }
|
||||
poksho = { path = "../poksho" }
|
||||
signal-crypto = { path = "../crypto" }
|
||||
zkcredential = { path = "../zkcredential" }
|
||||
|
@ -17,7 +17,7 @@ fn benchmark_integration_auth(c: &mut Criterion) {
|
||||
let group_public_params = group_secret_params.get_public_params();
|
||||
|
||||
// Random UID and issueTime
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let redemption_time = 123456u32;
|
||||
|
||||
// SERVER
|
||||
@ -101,7 +101,7 @@ pub fn benchmark_integration_profile(c: &mut Criterion) {
|
||||
zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key);
|
||||
let group_public_params = group_secret_params.get_public_params();
|
||||
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let profile_key =
|
||||
zkgroup::profiles::ProfileKey::create(zkgroup::common::constants::TEST_ARRAY_32_1);
|
||||
let profile_key_commitment = profile_key.get_commitment(aci);
|
||||
|
@ -33,7 +33,7 @@ pub struct CallLinkAuthCredentialResponse {
|
||||
|
||||
impl CallLinkAuthCredentialResponse {
|
||||
pub fn issue_credential(
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
redemption_time: Timestamp,
|
||||
params: &GenericServerSecretParams,
|
||||
randomness: RandomnessBytes,
|
||||
@ -50,7 +50,7 @@ impl CallLinkAuthCredentialResponse {
|
||||
|
||||
pub fn receive(
|
||||
self,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
redemption_time: Timestamp,
|
||||
params: &GenericServerPublicParams,
|
||||
) -> Result<CallLinkAuthCredential, ZkGroupVerificationFailure> {
|
||||
@ -81,7 +81,7 @@ pub struct CallLinkAuthCredential {
|
||||
impl CallLinkAuthCredential {
|
||||
pub fn present(
|
||||
&self,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
redemption_time: Timestamp,
|
||||
server_params: &GenericServerPublicParams,
|
||||
call_link_params: &CallLinkSecretParams,
|
||||
|
@ -95,7 +95,7 @@ pub struct CreateCallLinkCredentialRequest {
|
||||
impl CreateCallLinkCredentialRequest {
|
||||
pub fn issue(
|
||||
&self,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
timestamp: Timestamp,
|
||||
params: &GenericServerSecretParams,
|
||||
randomness: RandomnessBytes,
|
||||
@ -124,7 +124,7 @@ impl CreateCallLinkCredentialRequestContext {
|
||||
pub fn receive(
|
||||
self,
|
||||
response: CreateCallLinkCredentialResponse,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
params: &GenericServerPublicParams,
|
||||
) -> Result<CreateCallLinkCredential, ZkGroupVerificationFailure> {
|
||||
if response.timestamp % SECONDS_PER_DAY != 0 {
|
||||
@ -162,7 +162,7 @@ impl CreateCallLinkCredential {
|
||||
pub fn present(
|
||||
&self,
|
||||
room_id: &[u8],
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
server_params: &GenericServerPublicParams,
|
||||
call_link_params: &CallLinkSecretParams,
|
||||
randomness: RandomnessBytes,
|
||||
|
@ -45,7 +45,7 @@ impl CallLinkSecretParams {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encrypt_uid(&self, user_id: libsignal_protocol::Aci) -> api::groups::UuidCiphertext {
|
||||
pub fn encrypt_uid(&self, user_id: libsignal_core::Aci) -> api::groups::UuidCiphertext {
|
||||
let uid = crypto::uid_struct::UidStruct::from_service_id(user_id.into());
|
||||
self.encrypt_uid_struct(uid)
|
||||
}
|
||||
@ -64,7 +64,7 @@ impl CallLinkSecretParams {
|
||||
pub fn decrypt_uid(
|
||||
&self,
|
||||
ciphertext: api::groups::UuidCiphertext,
|
||||
) -> Result<libsignal_protocol::Aci, ZkGroupVerificationFailure> {
|
||||
) -> Result<libsignal_core::Aci, ZkGroupVerificationFailure> {
|
||||
let uid = crypto::uid_encryption::UidEncryptionDomain::decrypt(
|
||||
&self.uid_enc_key_pair,
|
||||
&ciphertext.ciphertext,
|
||||
|
@ -100,7 +100,7 @@ impl GroupSecretParams {
|
||||
|
||||
pub fn encrypt_service_id(
|
||||
&self,
|
||||
service_id: libsignal_protocol::ServiceId,
|
||||
service_id: libsignal_core::ServiceId,
|
||||
) -> api::groups::UuidCiphertext {
|
||||
let uid = crypto::uid_struct::UidStruct::from_service_id(service_id);
|
||||
self.encrypt_uid_struct(uid)
|
||||
@ -120,7 +120,7 @@ impl GroupSecretParams {
|
||||
pub fn decrypt_service_id(
|
||||
&self,
|
||||
ciphertext: api::groups::UuidCiphertext,
|
||||
) -> Result<libsignal_protocol::ServiceId, ZkGroupVerificationFailure> {
|
||||
) -> Result<libsignal_core::ServiceId, ZkGroupVerificationFailure> {
|
||||
crypto::uid_encryption::UidEncryptionDomain::decrypt(
|
||||
&self.uid_enc_key_pair,
|
||||
&ciphertext.ciphertext,
|
||||
@ -130,7 +130,7 @@ impl GroupSecretParams {
|
||||
pub fn encrypt_profile_key(
|
||||
&self,
|
||||
profile_key: api::profiles::ProfileKey,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
) -> api::groups::ProfileKeyCiphertext {
|
||||
self.encrypt_profile_key_bytes(profile_key.bytes, user_id)
|
||||
}
|
||||
@ -138,7 +138,7 @@ impl GroupSecretParams {
|
||||
pub fn encrypt_profile_key_bytes(
|
||||
&self,
|
||||
profile_key_bytes: ProfileKeyBytes,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
) -> api::groups::ProfileKeyCiphertext {
|
||||
let profile_key = crypto::profile_key_struct::ProfileKeyStruct::new(
|
||||
profile_key_bytes,
|
||||
@ -154,7 +154,7 @@ impl GroupSecretParams {
|
||||
pub fn decrypt_profile_key(
|
||||
&self,
|
||||
ciphertext: api::groups::ProfileKeyCiphertext,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
) -> Result<api::profiles::ProfileKey, ZkGroupVerificationFailure> {
|
||||
let profile_key_struct =
|
||||
crypto::profile_key_encryption::ProfileKeyEncryptionDomain::decrypt(
|
||||
|
@ -128,8 +128,8 @@ impl GroupSendCredentialResponse {
|
||||
self,
|
||||
params: &ServerPublicParams,
|
||||
group_params: &GroupSecretParams,
|
||||
user_ids: impl IntoIterator<Item = libsignal_protocol::ServiceId>,
|
||||
requester: libsignal_protocol::ServiceId,
|
||||
user_ids: impl IntoIterator<Item = libsignal_core::ServiceId>,
|
||||
requester: libsignal_core::ServiceId,
|
||||
now: Timestamp,
|
||||
) -> Result<GroupSendCredential, ZkGroupVerificationFailure> {
|
||||
if self.expiration % SECONDS_PER_DAY != 0 {
|
||||
@ -215,7 +215,7 @@ pub struct GroupSendCredentialPresentation {
|
||||
impl GroupSendCredentialPresentation {
|
||||
pub fn verify(
|
||||
&self,
|
||||
user_ids: impl IntoIterator<Item = libsignal_protocol::ServiceId>,
|
||||
user_ids: impl IntoIterator<Item = libsignal_core::ServiceId>,
|
||||
current_time_in_seconds: Timestamp,
|
||||
server_params: &ServerSecretParams,
|
||||
) -> Result<(), ZkGroupVerificationFailure> {
|
||||
|
@ -18,7 +18,7 @@ pub struct ExpiringProfileKeyCredential {
|
||||
}
|
||||
|
||||
impl ExpiringProfileKeyCredential {
|
||||
pub fn aci(&self) -> libsignal_protocol::Aci {
|
||||
pub fn aci(&self) -> libsignal_core::Aci {
|
||||
uuid::Uuid::from_bytes(self.aci_bytes).into()
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ impl ProfileKey {
|
||||
|
||||
pub fn get_commitment(
|
||||
&self,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
) -> api::profiles::ProfileKeyCommitment {
|
||||
let uid_bytes = uuid::Uuid::from(user_id).into_bytes();
|
||||
let profile_key = crypto::profile_key_struct::ProfileKeyStruct::new(self.bytes, uid_bytes);
|
||||
@ -51,7 +51,7 @@ impl ProfileKey {
|
||||
|
||||
pub fn get_profile_key_version(
|
||||
&self,
|
||||
user_id: libsignal_protocol::Aci,
|
||||
user_id: libsignal_core::Aci,
|
||||
) -> api::profiles::ProfileKeyVersion {
|
||||
let uid_bytes = uuid::Uuid::from(user_id).into_bytes();
|
||||
let mut combined_array = [0u8; PROFILE_KEY_LEN + UUID_LEN];
|
||||
|
@ -119,7 +119,7 @@ impl ServerSecretParams {
|
||||
pub fn issue_auth_credential(
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
aci: libsignal_protocol::Aci,
|
||||
aci: libsignal_core::Aci,
|
||||
redemption_time: CoarseRedemptionTime,
|
||||
) -> api::auth::AuthCredentialResponse {
|
||||
let mut sho = Sho::new(
|
||||
@ -148,8 +148,8 @@ impl ServerSecretParams {
|
||||
fn issue_auth_credential_with_pni(
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
aci: libsignal_protocol::Aci,
|
||||
pni: libsignal_protocol::Pni,
|
||||
aci: libsignal_core::Aci,
|
||||
pni: libsignal_core::Pni,
|
||||
redemption_time: Timestamp,
|
||||
encode_pni_as_aci_for_backward_compatibility: bool,
|
||||
) -> api::auth::AuthCredentialWithPniResponse {
|
||||
@ -160,7 +160,7 @@ impl ServerSecretParams {
|
||||
|
||||
let aci_struct = crypto::uid_struct::UidStruct::from_service_id(aci.into());
|
||||
let pni_struct = if encode_pni_as_aci_for_backward_compatibility {
|
||||
let pni_as_aci = libsignal_protocol::Aci::from(uuid::Uuid::from(pni));
|
||||
let pni_as_aci = libsignal_core::Aci::from(uuid::Uuid::from(pni));
|
||||
crypto::uid_struct::UidStruct::from_service_id(pni_as_aci.into())
|
||||
} else {
|
||||
crypto::uid_struct::UidStruct::from_service_id(pni.into())
|
||||
@ -186,8 +186,8 @@ impl ServerSecretParams {
|
||||
pub fn issue_auth_credential_with_pni_as_service_id(
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
aci: libsignal_protocol::Aci,
|
||||
pni: libsignal_protocol::Pni,
|
||||
aci: libsignal_core::Aci,
|
||||
pni: libsignal_core::Pni,
|
||||
redemption_time: Timestamp,
|
||||
) -> api::auth::AuthCredentialWithPniResponse {
|
||||
self.issue_auth_credential_with_pni(randomness, aci, pni, redemption_time, false)
|
||||
@ -196,8 +196,8 @@ impl ServerSecretParams {
|
||||
pub fn issue_auth_credential_with_pni_as_aci(
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
aci: libsignal_protocol::Aci,
|
||||
pni: libsignal_protocol::Pni,
|
||||
aci: libsignal_core::Aci,
|
||||
pni: libsignal_core::Pni,
|
||||
redemption_time: Timestamp,
|
||||
) -> api::auth::AuthCredentialWithPniResponse {
|
||||
self.issue_auth_credential_with_pni(randomness, aci, pni, redemption_time, true)
|
||||
@ -346,7 +346,7 @@ impl ServerSecretParams {
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
request: &api::profiles::ProfileKeyCredentialRequest,
|
||||
aci: libsignal_protocol::Aci,
|
||||
aci: libsignal_core::Aci,
|
||||
commitment: api::profiles::ProfileKeyCommitment,
|
||||
credential_expiration_time: Timestamp,
|
||||
) -> Result<api::profiles::ExpiringProfileKeyCredentialResponse, ZkGroupVerificationFailure>
|
||||
@ -456,7 +456,7 @@ impl ServerPublicParams {
|
||||
|
||||
pub fn receive_auth_credential(
|
||||
&self,
|
||||
aci: libsignal_protocol::Aci,
|
||||
aci: libsignal_core::Aci,
|
||||
redemption_time: CoarseRedemptionTime,
|
||||
response: &api::auth::AuthCredentialResponse,
|
||||
) -> Result<api::auth::AuthCredential, ZkGroupVerificationFailure> {
|
||||
@ -478,8 +478,8 @@ impl ServerPublicParams {
|
||||
|
||||
fn receive_auth_credential_with_pni(
|
||||
&self,
|
||||
aci: libsignal_protocol::Aci,
|
||||
pni: libsignal_protocol::Pni,
|
||||
aci: libsignal_core::Aci,
|
||||
pni: libsignal_core::Pni,
|
||||
redemption_time: Timestamp,
|
||||
response: &api::auth::AuthCredentialWithPniResponse,
|
||||
encode_pni_as_aci_for_backward_compatibility: bool,
|
||||
@ -489,7 +489,7 @@ impl ServerPublicParams {
|
||||
// Older AuthCredentialWithPnis used the same encoding for PNIs as ACIs.
|
||||
// This won't match up with UuidCiphertexts that hold correctly-encoded PNIs,
|
||||
// but can still be used as a valid ACI credential.
|
||||
let pni_as_aci = libsignal_protocol::Aci::from(uuid::Uuid::from(pni));
|
||||
let pni_as_aci = libsignal_core::Aci::from(uuid::Uuid::from(pni));
|
||||
crypto::uid_struct::UidStruct::from_service_id(pni_as_aci.into())
|
||||
} else {
|
||||
crypto::uid_struct::UidStruct::from_service_id(pni.into())
|
||||
@ -513,8 +513,8 @@ impl ServerPublicParams {
|
||||
|
||||
pub fn receive_auth_credential_with_pni_as_service_id(
|
||||
&self,
|
||||
aci: libsignal_protocol::Aci,
|
||||
pni: libsignal_protocol::Pni,
|
||||
aci: libsignal_core::Aci,
|
||||
pni: libsignal_core::Pni,
|
||||
redemption_time: Timestamp,
|
||||
response: &api::auth::AuthCredentialWithPniResponse,
|
||||
) -> Result<api::auth::AuthCredentialWithPni, ZkGroupVerificationFailure> {
|
||||
@ -523,8 +523,8 @@ impl ServerPublicParams {
|
||||
|
||||
pub fn receive_auth_credential_with_pni_as_aci(
|
||||
&self,
|
||||
aci: libsignal_protocol::Aci,
|
||||
pni: libsignal_protocol::Pni,
|
||||
aci: libsignal_core::Aci,
|
||||
pni: libsignal_core::Pni,
|
||||
redemption_time: Timestamp,
|
||||
response: &api::auth::AuthCredentialWithPniResponse,
|
||||
) -> Result<api::auth::AuthCredentialWithPni, ZkGroupVerificationFailure> {
|
||||
@ -614,7 +614,7 @@ impl ServerPublicParams {
|
||||
pub fn create_profile_key_credential_request_context(
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
aci: libsignal_protocol::Aci,
|
||||
aci: libsignal_core::Aci,
|
||||
profile_key: api::profiles::ProfileKey,
|
||||
) -> api::profiles::ProfileKeyCredentialRequestContext {
|
||||
let mut sho = Sho::new(
|
||||
|
@ -513,7 +513,7 @@ mod tests {
|
||||
|
||||
let uid_bytes = TEST_ARRAY_16;
|
||||
let redemption_time = 37;
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(uid_bytes);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(uid_bytes);
|
||||
let uid = uid_struct::UidStruct::from_service_id(aci.into());
|
||||
let credential = keypair.create_auth_credential(uid, redemption_time, &mut sho);
|
||||
let proof = proofs::AuthCredentialIssuanceProof::new(
|
||||
|
@ -557,7 +557,7 @@ impl ExpiringProfileKeyCredentialIssuanceProof {
|
||||
credential_expiration_time: Timestamp,
|
||||
) -> Result<(), ZkGroupVerificationFailure> {
|
||||
let credentials_system = credentials::SystemParams::get_hardcoded();
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(aci_bytes);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(aci_bytes);
|
||||
let uid = uid_struct::UidStruct::from_service_id(aci.into());
|
||||
|
||||
let m5 = TimestampStruct::calc_m_from(credential_expiration_time);
|
||||
@ -1118,7 +1118,7 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
let credentials_system = credentials::SystemParams::get_hardcoded();
|
||||
let uid_system = uid_encryption::SystemParams::get_hardcoded();
|
||||
let profile_key_system = profile_key_encryption::SystemParams::get_hardcoded();
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(aci_bytes);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(aci_bytes);
|
||||
let uid = uid_struct::UidStruct::from_service_id(aci.into());
|
||||
let profile_key = profile_key_struct::ProfileKeyStruct::new(profile_key_bytes, aci_bytes);
|
||||
|
||||
|
@ -71,7 +71,7 @@ impl UidEncryptionDomain {
|
||||
pub(crate) fn decrypt(
|
||||
key_pair: &KeyPair,
|
||||
ciphertext: &Ciphertext,
|
||||
) -> Result<libsignal_protocol::ServiceId, ZkGroupVerificationFailure> {
|
||||
) -> Result<libsignal_core::ServiceId, ZkGroupVerificationFailure> {
|
||||
let M2 = key_pair
|
||||
.decrypt_to_second_point(ciphertext)
|
||||
.map_err(|_| ZkGroupVerificationFailure)?;
|
||||
@ -86,8 +86,8 @@ impl UidEncryptionDomain {
|
||||
// the end, and which one is data-dependent. But it is constant-time.
|
||||
let decoded_uuid = uuid::Uuid::from_bytes(bytes);
|
||||
let decoded_service_ids = [
|
||||
libsignal_protocol::Aci::from(decoded_uuid).into(),
|
||||
libsignal_protocol::Pni::from(decoded_uuid).into(),
|
||||
libsignal_core::Aci::from(decoded_uuid).into(),
|
||||
libsignal_core::Pni::from(decoded_uuid).into(),
|
||||
];
|
||||
let decoded_aci = &decoded_service_ids[0];
|
||||
let decoded_pni = &decoded_service_ids[1];
|
||||
@ -132,7 +132,7 @@ mod tests {
|
||||
let key_pair2: KeyPair = bincode::deserialize(&key_pair_bytes).unwrap();
|
||||
assert!(key_pair == key_pair2);
|
||||
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let uid = uid_struct::UidStruct::from_service_id(aci.into());
|
||||
let ciphertext = key_pair.encrypt(&uid);
|
||||
|
||||
@ -154,7 +154,7 @@ mod tests {
|
||||
);
|
||||
|
||||
let plaintext = UidEncryptionDomain::decrypt(&key_pair, &ciphertext2).unwrap();
|
||||
assert!(matches!(plaintext, libsignal_protocol::ServiceId::Aci(_)));
|
||||
assert!(matches!(plaintext, libsignal_core::ServiceId::Aci(_)));
|
||||
assert!(uid_struct::UidStruct::from_service_id(plaintext) == uid);
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ mod tests {
|
||||
let mut sho = Sho::new(b"Test_Pni_Encryption", &[]);
|
||||
let key_pair = KeyPair::derive_from(sho.as_mut());
|
||||
|
||||
let pni = libsignal_protocol::Pni::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let pni = libsignal_core::Pni::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let uid = uid_struct::UidStruct::from_service_id(pni.into());
|
||||
let ciphertext = key_pair.encrypt(&uid);
|
||||
|
||||
@ -174,7 +174,7 @@ mod tests {
|
||||
assert!(ciphertext == ciphertext2);
|
||||
|
||||
let plaintext = UidEncryptionDomain::decrypt(&key_pair, &ciphertext2).unwrap();
|
||||
assert!(matches!(plaintext, libsignal_protocol::ServiceId::Pni(_)));
|
||||
assert!(matches!(plaintext, libsignal_core::ServiceId::Pni(_)));
|
||||
assert!(uid_struct::UidStruct::from_service_id(plaintext) == uid);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
use crate::common::sho::*;
|
||||
use crate::common::simple_types::*;
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use libsignal_protocol::ServiceId;
|
||||
use libsignal_core::ServiceId;
|
||||
use partial_default::PartialDefault;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::Sha256;
|
||||
|
@ -36,7 +36,7 @@ fn test_mac_generic() {
|
||||
let label = b"20221221_AuthCredentialLike";
|
||||
|
||||
let uid_bytes = TEST_ARRAY_16;
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(uid_bytes);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(uid_bytes);
|
||||
let uid = UidStruct::from_service_id(aci.into());
|
||||
|
||||
let proof = IssuanceProofBuilder::new(label)
|
||||
@ -83,7 +83,7 @@ fn test_mac_generic_without_verifying_encryption_key() {
|
||||
let label = b"20221221_AuthCredentialLike";
|
||||
|
||||
let uid_bytes = TEST_ARRAY_16;
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(uid_bytes);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(uid_bytes);
|
||||
let uid = UidStruct::from_service_id(aci.into());
|
||||
|
||||
let proof = IssuanceProofBuilder::new(label)
|
||||
@ -129,7 +129,7 @@ fn test_profile_key_credential() {
|
||||
|
||||
let label = b"20221221_ProfileKeyCredentialLike";
|
||||
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let uid = UidStruct::from_service_id(aci.into());
|
||||
let profile_key = ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16);
|
||||
let encrypted_profile_key = blinding_keypair.encrypt(&profile_key, &mut sho).into();
|
||||
@ -230,7 +230,7 @@ fn test_profile_key_credential_only_verifying_one_encryption_key() {
|
||||
|
||||
let label = b"20221221_ProfileKeyCredentialLike";
|
||||
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let uid = UidStruct::from_service_id(aci.into());
|
||||
let profile_key = ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16);
|
||||
let encrypted_profile_key = blinding_keypair.encrypt(&profile_key, &mut sho).into();
|
||||
@ -462,7 +462,7 @@ impl zkcredential::attributes::Domain for InverseUidDecryptionKey {
|
||||
|
||||
#[test]
|
||||
fn test_inverse_key() {
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(TEST_ARRAY_16);
|
||||
let uid = UidStruct::from_service_id(aci.into());
|
||||
|
||||
let mut sho = Sho::new(b"test_inverse_key", b"");
|
||||
|
@ -17,7 +17,7 @@ fn test_create_call_link_request_response() {
|
||||
let randomness4: RandomnessBytes = [0x46u8; RANDOMNESS_LEN];
|
||||
|
||||
// client receives in response to initial request
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let timestamp: Timestamp = DAY_ALIGNED_TIMESTAMP;
|
||||
|
||||
// known to client and redemption server
|
||||
@ -109,7 +109,7 @@ fn test_create_call_link_enforces_timestamp_granularity() {
|
||||
let randomness2: RandomnessBytes = [0x44u8; RANDOMNESS_LEN];
|
||||
|
||||
// client receives in response to initial request
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let timestamp: Timestamp = DAY_ALIGNED_TIMESTAMP + 60 * 60; // not on a day boundary!
|
||||
|
||||
// known to client and redemption server
|
||||
@ -151,7 +151,7 @@ fn test_auth_credential() {
|
||||
let randomness4: RandomnessBytes = [0x46u8; RANDOMNESS_LEN];
|
||||
|
||||
// client receives in response to initial request
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let timestamp: Timestamp = DAY_ALIGNED_TIMESTAMP;
|
||||
|
||||
// server generated materials; issuance request -> issuance response
|
||||
@ -225,7 +225,7 @@ fn test_auth_credential_enforces_timestamp_granularity() {
|
||||
let randomness2: RandomnessBytes = [0x44u8; RANDOMNESS_LEN];
|
||||
|
||||
// client receives in response to initial request
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let timestamp: Timestamp = DAY_ALIGNED_TIMESTAMP + 60 * 60; // not on a day boundary!
|
||||
|
||||
// server generated materials; issuance request -> issuance response
|
||||
|
@ -16,12 +16,12 @@ fn test_credential() {
|
||||
let randomness4: RandomnessBytes = [0x46u8; RANDOMNESS_LEN];
|
||||
|
||||
// first set up a group
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
|
||||
let moxie_user_id =
|
||||
libsignal_protocol::Aci::from(uuid::uuid!("e36fdce7-36da-4c6f-a21b-9afe2b754650"));
|
||||
libsignal_core::Aci::from(uuid::uuid!("e36fdce7-36da-4c6f-a21b-9afe2b754650"));
|
||||
let brian_user_id =
|
||||
libsignal_protocol::Aci::from(uuid::uuid!("8c78cd2a-16ff-427d-83dc-1a5e36ce713d"));
|
||||
libsignal_core::Aci::from(uuid::uuid!("8c78cd2a-16ff-427d-83dc-1a5e36ce713d"));
|
||||
|
||||
let group_members = [
|
||||
client_user_id.into(),
|
||||
@ -79,7 +79,7 @@ fn test_empty_credential_can_be_issued_and_received() {
|
||||
let randomness3: RandomnessBytes = [0x45u8; RANDOMNESS_LEN];
|
||||
|
||||
// first set up a group
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
|
||||
let group_secret_params = zkgroup::groups::GroupSecretParams::generate(randomness1);
|
||||
let client_user_id_ciphertext = group_secret_params.encrypt_service_id(client_user_id.into());
|
||||
@ -114,12 +114,12 @@ fn test_client_rejects_bad_expirations() {
|
||||
let randomness3: RandomnessBytes = [0x45u8; RANDOMNESS_LEN];
|
||||
|
||||
// first set up a group
|
||||
let client_user_id = libsignal_protocol::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
let client_user_id = libsignal_core::Aci::from_uuid_bytes([0x04u8; UUID_LEN]);
|
||||
|
||||
let moxie_user_id =
|
||||
libsignal_protocol::Aci::from(uuid::uuid!("e36fdce7-36da-4c6f-a21b-9afe2b754650"));
|
||||
libsignal_core::Aci::from(uuid::uuid!("e36fdce7-36da-4c6f-a21b-9afe2b754650"));
|
||||
let brian_user_id =
|
||||
libsignal_protocol::Aci::from(uuid::uuid!("8c78cd2a-16ff-427d-83dc-1a5e36ce713d"));
|
||||
libsignal_core::Aci::from(uuid::uuid!("8c78cd2a-16ff-427d-83dc-1a5e36ce713d"));
|
||||
|
||||
let group_members = [
|
||||
client_user_id.into(),
|
||||
|
@ -56,7 +56,7 @@ fn test_integration_auth() {
|
||||
let group_public_params = group_secret_params.get_public_params();
|
||||
|
||||
// Random UID and issueTime
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let redemption_time = 123456u32;
|
||||
|
||||
// SERVER
|
||||
@ -184,8 +184,8 @@ fn test_integration_auth_with_pni() {
|
||||
let group_public_params = group_secret_params.get_public_params();
|
||||
|
||||
// Random UID and issueTime
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let pni = libsignal_protocol::Pni::from_uuid_bytes(zkgroup::TEST_ARRAY_16_1);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let pni = libsignal_core::Pni::from_uuid_bytes(zkgroup::TEST_ARRAY_16_1);
|
||||
let redemption_time = 123456 * SECONDS_PER_DAY;
|
||||
|
||||
// SERVER
|
||||
@ -312,8 +312,8 @@ fn test_integration_auth_with_pni_using_pni_as_aci() {
|
||||
let group_public_params = group_secret_params.get_public_params();
|
||||
|
||||
// Random UID and issueTime
|
||||
let aci = libsignal_protocol::Aci::from(uuid::Uuid::from_bytes(zkgroup::TEST_ARRAY_16));
|
||||
let pni = libsignal_protocol::Pni::from(uuid::Uuid::from_bytes(zkgroup::TEST_ARRAY_16_1));
|
||||
let aci = libsignal_core::Aci::from(uuid::Uuid::from_bytes(zkgroup::TEST_ARRAY_16));
|
||||
let pni = libsignal_core::Pni::from(uuid::Uuid::from_bytes(zkgroup::TEST_ARRAY_16_1));
|
||||
let redemption_time = 123456 * SECONDS_PER_DAY;
|
||||
|
||||
// SERVER
|
||||
@ -378,7 +378,7 @@ fn test_integration_auth_with_pni_using_pni_as_aci() {
|
||||
assert!(
|
||||
presentation_any.get_pni_ciphertext().unwrap()
|
||||
== group_secret_params
|
||||
.encrypt_service_id(libsignal_protocol::Aci::from(uuid::Uuid::from(pni)).into())
|
||||
.encrypt_service_id(libsignal_core::Aci::from(uuid::Uuid::from(pni)).into())
|
||||
);
|
||||
|
||||
server_secret_params
|
||||
@ -426,7 +426,7 @@ fn test_integration_expiring_profile() {
|
||||
zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key);
|
||||
let group_public_params = group_secret_params.get_public_params();
|
||||
|
||||
let aci = libsignal_protocol::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let aci = libsignal_core::Aci::from_uuid_bytes(zkgroup::TEST_ARRAY_16);
|
||||
let profile_key =
|
||||
zkgroup::profiles::ProfileKey::create(zkgroup::common::constants::TEST_ARRAY_32_1);
|
||||
let profile_key_commitment = profile_key.get_commitment(aci);
|
||||
|
Loading…
Reference in New Issue
Block a user