Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Forge, RForge and JForge algorithms #4

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 282 additions & 0 deletions src/amf/franking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,139 @@ pub fn judge(
b1 && b2
}

pub fn forge(
sender_public_key: AMFPublicKey,
_recipient_public_key: AMFPublicKey,
judge_public_key: AMFPublicKey,
message: &[u8],
) -> AMFSignature {
let mut rng = rand::thread_rng();
let g = RistrettoBasepointTable::basepoint(&RISTRETTO_BASEPOINT_TABLE);
// cf. Fig. 5 in [AMF]
let alpha = Scalar::random(&mut rng);
let beta = Scalar::random(&mut rng);
let gamma = Scalar::random(&mut rng);
let delta = Scalar::random(&mut rng);

let J = gamma * g;
let R = delta * g;
let E_J = alpha * g;
let E_R = beta * g;

let mut spok = AMFSPoK::new(
sender_public_key.public_key,
judge_public_key.public_key,
J,
R,
E_J,
);
let pi = spok.sign(
FiatShamirSecretKey {
witness: (
OrWitness {
b: true,
s0_witness: None,
s1_witness: Some(gamma),
},
OrWitness {
b: true,
s0_witness: None,
s1_witness: Some(delta),
},
),
},
message,
);
AMFSignature { pi, J, R, E_J, E_R }
}

pub fn r_forge(
sender_public_key: AMFPublicKey,
recipient_secret_key: AMFSecretKey,
judge_public_key: AMFPublicKey,
message: &[u8],
) -> AMFSignature {
let mut rng = rand::thread_rng();
let g = RistrettoBasepointTable::basepoint(&RISTRETTO_BASEPOINT_TABLE);
// cf. Fig. 5 in [AMF]
let alpha = Scalar::random(&mut rng);
let beta = Scalar::random(&mut rng);
let gamma = Scalar::random(&mut rng);

let recipient_public_key = recipient_secret_key.secret_key * g;

let J = gamma * g;
let R = beta * recipient_public_key;
let E_J = alpha * g;
let E_R = beta * g;

let mut spok = AMFSPoK::new(
sender_public_key.public_key,
judge_public_key.public_key,
J,
R,
E_J,
);
let pi = spok.sign(
FiatShamirSecretKey {
witness: (
OrWitness {
b: true,
s0_witness: None,
s1_witness: Some(gamma),
},
OrWitness {
b: true,
s0_witness: None,
s1_witness: Some(beta * recipient_secret_key.secret_key),
},
),
},
message,
);
AMFSignature { pi, J, R, E_J, E_R }
}

pub fn j_forge(
sender_public_key: AMFPublicKey,
recipient_public_key: AMFPublicKey,
judge_secret_key: AMFSecretKey,
message: &[u8],
) -> AMFSignature {
let mut rng = rand::thread_rng();
let g = RistrettoBasepointTable::basepoint(&RISTRETTO_BASEPOINT_TABLE);
// cf. Fig. 5 in [AMF]
let alpha = Scalar::random(&mut rng);
let beta = Scalar::random(&mut rng);

let judge_public_key = judge_secret_key.secret_key * g;

let J = alpha * judge_public_key;
let R = beta * recipient_public_key.public_key;
let E_J = alpha * g;
let E_R = beta * g;

let mut spok = AMFSPoK::new(sender_public_key.public_key, judge_public_key, J, R, E_J);
let pi = spok.sign(
FiatShamirSecretKey {
witness: (
OrWitness {
b: true,
s0_witness: None,
s1_witness: Some(alpha * judge_secret_key.secret_key),
},
OrWitness {
b: false,
s0_witness: Some(alpha),
s1_witness: None,
},
),
},
message,
);
AMFSignature { pi, J, R, E_J, E_R }
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -209,4 +342,153 @@ mod tests {
);
assert!(judging_result);
}

#[test]
fn test_forge() {
let (sender_public_key, _sender_secret_key) = keygen(AMFRole::Sender);
let (recipient_public_key, recipient_secret_key) = keygen(AMFRole::Recipient);
let (judge_public_key, judge_secret_key) = keygen(AMFRole::Judge);

let message = b"hello world!";

// Forge an AMF signature for "universal deniability"
let amf_signature = forge(
sender_public_key,
recipient_public_key,
judge_public_key,
message,
);

// The forged signature should NOT be verified by the recipient
let verification_result = verify(
recipient_secret_key,
sender_public_key,
recipient_public_key,
judge_public_key,
message,
amf_signature,
);
assert!(!verification_result);

// The forged signature should NOT be judged by the judge, as the judge can detect the forgery
let judging_result = judge(
judge_secret_key,
sender_public_key,
recipient_public_key,
judge_public_key,
message,
amf_signature,
);
assert!(!judging_result);

// The forged signature should look valid
let spok = AMFSPoK::new(
sender_public_key.public_key,
judge_public_key.public_key,
amf_signature.J,
amf_signature.R,
amf_signature.E_J,
);
assert!(spok.verify(message, amf_signature.pi));
}

#[test]
fn test_r_forge() {
let (sender_public_key, _sender_secret_key) = keygen(AMFRole::Sender);
let (recipient_public_key, recipient_secret_key) = keygen(AMFRole::Recipient);
let (judge_public_key, judge_secret_key) = keygen(AMFRole::Judge);

let message = b"hello world!";

// Forge the AMF signature using the recipient's secret key
// This enables "receiver compromise deniability"
let amf_signature = r_forge(
sender_public_key,
recipient_secret_key,
judge_public_key,
message,
);

// The forged signature should be verified by any party with the recipient's secret key
let verification_result = verify(
recipient_secret_key,
sender_public_key,
recipient_public_key,
judge_public_key,
message,
amf_signature,
);
assert!(verification_result);

// The forged signature should NOT be judged by the judge, as the judge can detect the forgery
// This is what maintains "receiver binding"
let judging_result = judge(
judge_secret_key,
sender_public_key,
recipient_public_key,
judge_public_key,
message,
amf_signature,
);
assert!(!judging_result);

// The forged signature should look valid
let spok = AMFSPoK::new(
sender_public_key.public_key,
judge_public_key.public_key,
amf_signature.J,
amf_signature.R,
amf_signature.E_J,
);
assert!(spok.verify(message, amf_signature.pi));
}

#[test]
fn test_j_forge() {
let (sender_public_key, _sender_secret_key) = keygen(AMFRole::Sender);
let (recipient_public_key, recipient_secret_key) = keygen(AMFRole::Recipient);
let (judge_public_key, judge_secret_key) = keygen(AMFRole::Judge);

let message = b"hello world!";

// Forge an AMF signature for "judge compromise deniability"
let amf_signature = j_forge(
sender_public_key,
recipient_public_key,
judge_secret_key,
message,
);

// The forged signature should be verified by the recipient
let verification_result = verify(
recipient_secret_key,
sender_public_key,
recipient_public_key,
judge_public_key,
message,
amf_signature,
);
assert!(verification_result);

// The forged signature should be judged by the judge
let judging_result = judge(
judge_secret_key,
sender_public_key,
recipient_public_key,
judge_public_key,
message,
amf_signature,
);
assert!(judging_result);

// The forged signature should look valid
let spok = AMFSPoK::new(
sender_public_key.public_key,
judge_public_key.public_key,
amf_signature.J,
amf_signature.R,
amf_signature.E_J,
);
assert!(spok.verify(message, amf_signature.pi));
}
}