mirror of
https://github.com/signalapp/libsignal.git
synced 2026-04-25 17:25:18 +02:00
zkgroup: Bind C_y5 in ProfileKeyCredential proof
This commit is contained in:
@@ -258,7 +258,7 @@ fn ServerPublicParams_CreateExpiringProfileKeyCredentialPresentationDeterministi
|
||||
*randomness,
|
||||
group_secret_params.into_inner(),
|
||||
profile_key_credential.into_inner(),
|
||||
),
|
||||
) as &zkgroup::profiles::ExpiringProfileKeyCredentialPresentation,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -217,11 +217,12 @@ pub fn benchmark_integration_profile(c: &mut Criterion) {
|
||||
// Create presentation
|
||||
let randomness = zkgroup::TEST_ARRAY_32_5;
|
||||
|
||||
let presentation = server_public_params.create_expiring_profile_key_credential_presentation(
|
||||
randomness,
|
||||
group_secret_params,
|
||||
profile_key_credential,
|
||||
);
|
||||
let presentation: zkgroup::profiles::ExpiringProfileKeyCredentialPresentation =
|
||||
server_public_params.create_expiring_profile_key_credential_presentation(
|
||||
randomness,
|
||||
group_secret_params,
|
||||
profile_key_credential,
|
||||
);
|
||||
|
||||
c.bench_function("create_expiring_profile_key_credential_presentation", |b| {
|
||||
b.iter(|| {
|
||||
@@ -229,7 +230,7 @@ pub fn benchmark_integration_profile(c: &mut Criterion) {
|
||||
randomness,
|
||||
group_secret_params,
|
||||
profile_key_credential,
|
||||
)
|
||||
) as zkgroup::profiles::ExpiringProfileKeyCredentialPresentation
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -62,15 +62,19 @@ impl ProfileKeyCredentialPresentationV2 {
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, PartialDefault)]
|
||||
pub struct ExpiringProfileKeyCredentialPresentation {
|
||||
pub(crate) version: VersionByte<PRESENTATION_VERSION_3>,
|
||||
pub struct ExpiringProfileKeyCredentialPresentation<const V: u8 = PRESENTATION_VERSION_3> {
|
||||
pub(crate) version: VersionByte<V>,
|
||||
pub(crate) proof: crypto::proofs::ExpiringProfileKeyCredentialPresentationProof,
|
||||
pub(crate) uid_enc_ciphertext: crypto::uid_encryption::Ciphertext,
|
||||
pub(crate) profile_key_enc_ciphertext: crypto::profile_key_encryption::Ciphertext,
|
||||
pub(crate) credential_expiration_time: Timestamp,
|
||||
}
|
||||
|
||||
impl ExpiringProfileKeyCredentialPresentation {
|
||||
// The only thing that changes in V2 is the proof contents, so we can reuse the same structure.
|
||||
pub type ExpiringProfileKeyCredentialPresentationV2 =
|
||||
ExpiringProfileKeyCredentialPresentation<PRESENTATION_VERSION_4>;
|
||||
|
||||
impl<const V: u8> ExpiringProfileKeyCredentialPresentation<V> {
|
||||
pub fn get_uuid_ciphertext(&self) -> api::groups::UuidCiphertext {
|
||||
api::groups::UuidCiphertext {
|
||||
reserved: Default::default(),
|
||||
@@ -95,6 +99,7 @@ pub enum AnyProfileKeyCredentialPresentation {
|
||||
V1(ProfileKeyCredentialPresentationV1),
|
||||
V2(ProfileKeyCredentialPresentationV2),
|
||||
V3(ExpiringProfileKeyCredentialPresentation),
|
||||
V4(ExpiringProfileKeyCredentialPresentationV2),
|
||||
}
|
||||
|
||||
impl AnyProfileKeyCredentialPresentation {
|
||||
@@ -112,6 +117,10 @@ impl AnyProfileKeyCredentialPresentation {
|
||||
crate::deserialize::<ExpiringProfileKeyCredentialPresentation>(presentation_bytes)
|
||||
.map(AnyProfileKeyCredentialPresentation::V3)
|
||||
}
|
||||
PRESENTATION_VERSION_4 => {
|
||||
crate::deserialize::<ExpiringProfileKeyCredentialPresentationV2>(presentation_bytes)
|
||||
.map(AnyProfileKeyCredentialPresentation::V4)
|
||||
}
|
||||
_ => Err(ZkGroupDeserializationFailure::new::<Self>()),
|
||||
}
|
||||
}
|
||||
@@ -127,6 +136,9 @@ impl AnyProfileKeyCredentialPresentation {
|
||||
AnyProfileKeyCredentialPresentation::V3(presentation) => {
|
||||
presentation.get_uuid_ciphertext()
|
||||
}
|
||||
AnyProfileKeyCredentialPresentation::V4(presentation) => {
|
||||
presentation.get_uuid_ciphertext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +153,9 @@ impl AnyProfileKeyCredentialPresentation {
|
||||
AnyProfileKeyCredentialPresentation::V3(presentation) => {
|
||||
presentation.get_profile_key_ciphertext()
|
||||
}
|
||||
AnyProfileKeyCredentialPresentation::V4(presentation) => {
|
||||
presentation.get_profile_key_ciphertext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +190,9 @@ impl Serialize for AnyProfileKeyCredentialPresentation {
|
||||
AnyProfileKeyCredentialPresentation::V3(presentation) => {
|
||||
presentation.serialize(serializer)
|
||||
}
|
||||
AnyProfileKeyCredentialPresentation::V4(presentation) => {
|
||||
presentation.serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,13 +209,19 @@ impl ServerSecretParams {
|
||||
presentation,
|
||||
current_time,
|
||||
),
|
||||
api::profiles::AnyProfileKeyCredentialPresentation::V4(presentation) => self
|
||||
.verify_expiring_profile_key_credential_presentation(
|
||||
group_public_params,
|
||||
presentation,
|
||||
current_time,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_expiring_profile_key_credential_presentation(
|
||||
pub fn verify_expiring_profile_key_credential_presentation<const V: u8>(
|
||||
&self,
|
||||
group_public_params: api::groups::GroupPublicParams,
|
||||
presentation: &api::profiles::ExpiringProfileKeyCredentialPresentation,
|
||||
presentation: &api::profiles::ExpiringProfileKeyCredentialPresentation<V>,
|
||||
current_time: Timestamp,
|
||||
) -> Result<(), ZkGroupVerificationFailure> {
|
||||
let credentials_key_pair = self.expiring_profile_key_credentials_key_pair;
|
||||
@@ -229,6 +235,7 @@ impl ServerSecretParams {
|
||||
presentation.profile_key_enc_ciphertext,
|
||||
profile_key_enc_public_key,
|
||||
presentation.credential_expiration_time,
|
||||
V >= PRESENTATION_VERSION_4,
|
||||
)?;
|
||||
|
||||
if presentation.credential_expiration_time <= current_time {
|
||||
@@ -436,12 +443,12 @@ impl ServerPublicParams {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_expiring_profile_key_credential_presentation(
|
||||
pub fn create_expiring_profile_key_credential_presentation<const V: u8>(
|
||||
&self,
|
||||
randomness: RandomnessBytes,
|
||||
group_secret_params: api::groups::GroupSecretParams,
|
||||
expiring_profile_key_credential: api::profiles::ExpiringProfileKeyCredential,
|
||||
) -> api::profiles::ExpiringProfileKeyCredentialPresentation {
|
||||
) -> api::profiles::ExpiringProfileKeyCredentialPresentation<V> {
|
||||
let mut sho = Sho::new(
|
||||
b"Signal_ZKGroup_20220508_Random_ServerPublicParams_CreateExpiringProfileKeyCredentialPresentation",
|
||||
&randomness,
|
||||
@@ -465,6 +472,7 @@ impl ServerPublicParams {
|
||||
profile_key_ciphertext.ciphertext,
|
||||
expiring_profile_key_credential.aci_bytes,
|
||||
expiring_profile_key_credential.profile_key_bytes,
|
||||
V >= PRESENTATION_VERSION_4,
|
||||
&mut sho,
|
||||
);
|
||||
|
||||
|
||||
@@ -448,7 +448,7 @@ impl ProfileKeyCredentialPresentationProofV1 {
|
||||
}
|
||||
|
||||
impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
pub fn get_poksho_statement() -> poksho::Statement {
|
||||
pub fn get_poksho_statement(full_checking: bool) -> poksho::Statement {
|
||||
let mut st = poksho::Statement::new();
|
||||
st.add("Z", &[("z", "I")]);
|
||||
st.add("C_x1", &[("t", "C_x0"), ("z0", "G_x0"), ("z", "G_x1")]);
|
||||
@@ -467,6 +467,9 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
st.add("E_B1", &[("b1", "C_y3"), ("z2", "G_y3")]);
|
||||
st.add("0", &[("z1", "I"), ("a1", "Z")]);
|
||||
st.add("0", &[("z2", "I"), ("b1", "Z")]);
|
||||
if full_checking {
|
||||
st.add("C_y5", &[("z", "G_y5")]);
|
||||
}
|
||||
st
|
||||
}
|
||||
|
||||
@@ -480,6 +483,7 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
profile_key_ciphertext: profile_key_encryption::Ciphertext,
|
||||
aci_bytes: UidBytes,
|
||||
profile_key_bytes: ProfileKeyBytes,
|
||||
full_checking: bool,
|
||||
sho: &mut Sho,
|
||||
) -> Self {
|
||||
let credentials_system = credentials::SystemParams::get_hardcoded();
|
||||
@@ -557,7 +561,12 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
point_args.add("G_y3", credentials_system.G_y[3]);
|
||||
point_args.add("0", RistrettoPoint::identity());
|
||||
|
||||
let poksho_proof = Self::get_poksho_statement()
|
||||
if full_checking {
|
||||
point_args.add("C_y5", C_y5);
|
||||
point_args.add("G_y5", credentials_system.G_y[5]);
|
||||
}
|
||||
|
||||
let poksho_proof = Self::get_poksho_statement(full_checking)
|
||||
.prove(
|
||||
&scalar_args,
|
||||
&point_args,
|
||||
@@ -587,6 +596,7 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
profile_key_ciphertext: profile_key_encryption::Ciphertext,
|
||||
profile_key_enc_public_key: profile_key_encryption::PublicKey,
|
||||
credential_expiration_time: Timestamp,
|
||||
full_checking: bool,
|
||||
) -> Result<(), ZkGroupVerificationFailure> {
|
||||
let uid_enc_system = uid_encryption::SystemParams::get_hardcoded();
|
||||
let profile_key_enc_system = profile_key_encryption::SystemParams::get_hardcoded();
|
||||
@@ -604,8 +614,8 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
poksho_proof,
|
||||
} = self;
|
||||
|
||||
let (C_x0, C_x1, C_y1, C_y2, C_y3, C_y4, C_V) =
|
||||
(*C_x0, *C_x1, *C_y1, *C_y2, *C_y3, *C_y4, *C_V);
|
||||
let (C_x0, C_x1, C_y1, C_y2, C_y3, C_y4, C_y5, C_V) =
|
||||
(*C_x0, *C_x1, *C_y1, *C_y2, *C_y3, *C_y4, *C_y5, *C_V);
|
||||
|
||||
let credentials::KeyPair {
|
||||
W,
|
||||
@@ -661,7 +671,13 @@ impl ExpiringProfileKeyCredentialPresentationProof {
|
||||
point_args.add("G_y3", credentials_system.G_y[3]);
|
||||
point_args.add("0", RistrettoPoint::identity());
|
||||
|
||||
match Self::get_poksho_statement().verify_proof(poksho_proof, &point_args, &[]) {
|
||||
if full_checking {
|
||||
point_args.add("C_y5", C_y5);
|
||||
point_args.add("G_y5", credentials_system.G_y[5]);
|
||||
}
|
||||
|
||||
match Self::get_poksho_statement(full_checking).verify_proof(poksho_proof, &point_args, &[])
|
||||
{
|
||||
Err(_) => Err(ZkGroupVerificationFailure),
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ const PROFILE_KEY_CREDENTIAL_PRESENTATION_V3_RESULT: &[u8] = &hex!(
|
||||
"02fc58a4f2c9bd736238abfc28890c8b2363d084bee430692f05ee559bd37dea3378949e72b271fe0d815b6d908035106cd670b45892df40780c62c37fae106c41be38371fe042a4d4f697db112972d79204b3d48d1253d3231c22926e107f661d40897cb7fdb4777c1680a57008655db71efaac1f69cd9ddf8cda33b226662d7ba443416281508fcdbb026d63f83168470a83e12803a6d2ee2c907343f2f6b063fe6bf0f17a032fabe61e77e904dfe7d3042125728c1984c86a094a0e3991ba554c1ebf604c14a8b13c384c5c01909656c114b24f9d3615d3b14bde7ce9cf126aca3e073e804b2016f7c5affa158a3a68ed9024c6880ecb441a346e7e91aedd6240010000000000002e70f27fb3f4c58cb40dfe58ce1d122312969426abb0bbb820bfbc5ff61d400a419d5ddb7c30c546427273d4fca3096ee4dd2fd03ccbbd26304ffcfe54fef50db8538177ebc61117a222253b4d4189f795abbde3b3d8a0a72d97b7750e0394010a01b474c3e942ef1ee807e17421689c6ca793c4f30b09c989b8a9679aee130eb034f64a34dbcaf12616970d2c8d58ca715bf5c4d42475fa6a1b82ba31574e072506652253e86cd783e30e1c06d2e861ba864a5373759472b31c5b26a8e46d062b8b5da2ec0a3ba499648e80f307728b7815aa60d167a0a9d01c2d2cbfb0a60ddc9dfc5343564b5f021fd1adba6d2a389e7c331bfffeed2a5d1887634323840574e49255a62d9e00ffc21f56afbb12fb9660e185f979223ec714c01e403a3a0a3276d0ef78182f12c092f5237befe3f0afea7693370788f854ec697e44c9bd02765de9df4cfa5487f360e29e99343e91811baec331c4680985e608ca5d408e21725c6aa1b61d5a8b48d75f4aaa9a3cbe88d3e0f1a54319081f77c72c8f52547448c03ab4afbf6b8fb0e126c037a0ad4094600dd0e0634d76f88c21087f3cfb485a89bc1e3abc4c95041d1d170eccf02933ec5393d4be1dc573f83c33d3b9a7468069160000000000"
|
||||
);
|
||||
|
||||
const PROFILE_KEY_CREDENTIAL_PRESENTATION_V4_RESULT: &[u8] = &hex!(
|
||||
"03fc58a4f2c9bd736238abfc28890c8b2363d084bee430692f05ee559bd37dea3378949e72b271fe0d815b6d908035106cd670b45892df40780c62c37fae106c41be38371fe042a4d4f697db112972d79204b3d48d1253d3231c22926e107f661d40897cb7fdb4777c1680a57008655db71efaac1f69cd9ddf8cda33b226662d7ba443416281508fcdbb026d63f83168470a83e12803a6d2ee2c907343f2f6b063fe6bf0f17a032fabe61e77e904dfe7d3042125728c1984c86a094a0e3991ba554c1ebf604c14a8b13c384c5c01909656c114b24f9d3615d3b14bde7ce9cf126aca3e073e804b2016f7c5affa158a3a68ed9024c6880ecb441a346e7e91aedd6240010000000000006b4403e6adc3322acd34eea13fcc1ae971aab14386fa9b4d85ba0490dfca2f0d21de78e92719ad40a6a49d7549551a4bc6f7e4e4f0da81e9d6cc054da9529e053d1360b9d83e3ab9d3c8a9b7d3b07e2bab0979f3912c4bb41f621bf7685ee607fc147670196e009a9cd92b0fb525ca9b8e8fdf4c332732c02ccbcf57b5c19f001df37a5104d367f0f3f5cc0d9a2bd299e1f37872d7580b05596eadd5dec3e80366ab47357205c407bbcac49540a1fd69f36d308d0fdb72d0273f0c7a0d92220fe25daba5885a162bf238495463971c61b380084b7f79ad817d6f343e254722019da9ad32e72f2d864074023096cb8dd615b6fbbb47c6bef0926290a68403340e0a4dfb961e5b9002fc104e480823f12178cb91fafd51eb5dc9eb9fec4e6f7c0a130f31eb84cc70be9e5fd0bfb7d279590bdb49e7a4fe3b156a922fc73f78a50e765de9df4cfa5487f360e29e99343e91811baec331c4680985e608ca5d408e21725c6aa1b61d5a8b48d75f4aaa9a3cbe88d3e0f1a54319081f77c72c8f52547448c03ab4afbf6b8fb0e126c037a0ad4094600dd0e0634d76f88c21087f3cfb485a89bc1e3abc4c95041d1d170eccf02933ec5393d4be1dc573f83c33d3b9a7468069160000000000"
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn test_auth_credential_presentation_v1_is_rejected() {
|
||||
assert!(
|
||||
@@ -160,8 +164,11 @@ fn test_integration_auth_zkc() {
|
||||
auth_credential_bytes.copy_from_slice(&bincode::serialize(&auth_credential).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integration_expiring_profile() {
|
||||
fn test_integration_expiring_profile<const V: u8>()
|
||||
where
|
||||
zkgroup::profiles::AnyProfileKeyCredentialPresentation:
|
||||
From<zkgroup::profiles::ExpiringProfileKeyCredentialPresentation<V>>,
|
||||
{
|
||||
// SERVER
|
||||
let server_secret_params = zkgroup::ServerSecretParams::generate(zkgroup::TEST_ARRAY_32);
|
||||
let server_public_params = server_secret_params.get_public_params();
|
||||
@@ -226,11 +233,12 @@ fn test_integration_expiring_profile() {
|
||||
// Create presentation
|
||||
let randomness = zkgroup::TEST_ARRAY_32_5;
|
||||
|
||||
let presentation = server_public_params.create_expiring_profile_key_credential_presentation(
|
||||
randomness,
|
||||
group_secret_params,
|
||||
profile_key_credential,
|
||||
);
|
||||
let presentation: zkgroup::profiles::ExpiringProfileKeyCredentialPresentation<V> =
|
||||
server_public_params.create_expiring_profile_key_credential_presentation(
|
||||
randomness,
|
||||
group_secret_params,
|
||||
profile_key_credential,
|
||||
);
|
||||
assert_eq!(expiration, presentation.get_expiration_time());
|
||||
let presentation_bytes = &bincode::serialize(&presentation).unwrap();
|
||||
|
||||
@@ -238,15 +246,14 @@ fn test_integration_expiring_profile() {
|
||||
presentation.into();
|
||||
let presentation_any_bytes = &bincode::serialize(&presentation_any).unwrap();
|
||||
|
||||
assert_hex_eq!(
|
||||
PROFILE_KEY_CREDENTIAL_PRESENTATION_V3_RESULT[..],
|
||||
presentation_bytes[..]
|
||||
);
|
||||
let expected_hex = match V {
|
||||
zkgroup::PRESENTATION_VERSION_3 => PROFILE_KEY_CREDENTIAL_PRESENTATION_V3_RESULT,
|
||||
zkgroup::PRESENTATION_VERSION_4 => PROFILE_KEY_CREDENTIAL_PRESENTATION_V4_RESULT,
|
||||
_ => panic!("unexpected ExpiringProfileKeyCredentialPresentation version {V}"),
|
||||
};
|
||||
|
||||
assert_hex_eq!(
|
||||
PROFILE_KEY_CREDENTIAL_PRESENTATION_V3_RESULT[..],
|
||||
presentation_any_bytes[..]
|
||||
);
|
||||
assert_hex_eq!(expected_hex, &presentation_bytes[..]);
|
||||
assert_hex_eq!(expected_hex, &presentation_any_bytes[..]);
|
||||
|
||||
server_secret_params
|
||||
.verify_profile_key_credential_presentation(
|
||||
@@ -310,6 +317,16 @@ fn test_integration_expiring_profile() {
|
||||
profile_key_credential_response_bytes.copy_from_slice(&bincode::serialize(&response).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integration_expiring_profile_v1() {
|
||||
test_integration_expiring_profile::<{ zkgroup::PRESENTATION_VERSION_3 }>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integration_expiring_profile_v2() {
|
||||
test_integration_expiring_profile::<{ zkgroup::PRESENTATION_VERSION_4 }>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_sigs() {
|
||||
let server_secret_params =
|
||||
|
||||
Reference in New Issue
Block a user