confium_privacy/
proxy_reencryption.rs1use getrandom::SysRng;
14use p256::elliptic_curve::sec1::{FromSec1Point, ToSec1Point};
15use p256::{AffinePoint, ProjectivePoint, Scalar};
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Ciphertext {
21 pub c1_hex: String,
22 pub c2_hex: String,
23}
24
25#[derive(Debug, Clone)]
27pub struct ReEncryptionKey {
28 pub rk: Scalar,
30}
31
32pub fn generate_rk(alice_sk: &Scalar, _bob_pk: &AffinePoint) -> ReEncryptionKey {
34 ReEncryptionKey { rk: *alice_sk }
39}
40
41pub fn encrypt_point(pk: &AffinePoint, message: &AffinePoint) -> Ciphertext {
43 use p256::elliptic_curve::Field;
44 use p256::elliptic_curve::rand_core::UnwrapErr;
45 let r = Scalar::random(&mut UnwrapErr(SysRng));
46 let c1 = (ProjectivePoint::GENERATOR * r).to_affine();
47 let c2 = (ProjectivePoint::from(*pk) * r + ProjectivePoint::from(*message)).to_affine();
48 Ciphertext {
49 c1_hex: hex::encode(c1.to_sec1_point(true).as_bytes()),
50 c2_hex: hex::encode(c2.to_sec1_point(true).as_bytes()),
51 }
52}
53
54pub fn decrypt_point(sk: &Scalar, ct: &Ciphertext) -> Option<AffinePoint> {
56 let c1 = decode_point(&ct.c1_hex)?;
57 let c2 = decode_point(&ct.c2_hex)?;
58 let sk_c1 = ProjectivePoint::from(c1) * sk;
60 let m = ProjectivePoint::from(c2) - sk_c1;
61 Some(m.to_affine())
62}
63
64pub fn re_encrypt(rk: &ReEncryptionKey, ct: &Ciphertext) -> Ciphertext {
66 let c1 = decode_point(&ct.c1_hex).unwrap();
67 let new_c1 = (ProjectivePoint::from(c1) * rk.rk).to_affine();
69 Ciphertext {
70 c1_hex: hex::encode(new_c1.to_sec1_point(true).as_bytes()),
71 c2_hex: ct.c2_hex.clone(),
72 }
73}
74
75fn decode_point(hex_str: &str) -> Option<AffinePoint> {
76 let bytes = hex::decode(hex_str).ok()?;
77 let encoded =
78 p256::elliptic_curve::sec1::Sec1Point::<p256::NistP256>::from_bytes(&bytes).ok()?;
79 Option::<AffinePoint>::from(AffinePoint::from_sec1_point(&encoded))
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use p256::elliptic_curve::Field;
86 use p256::elliptic_curve::rand_core::UnwrapErr;
87
88 fn random_keypair() -> (Scalar, AffinePoint) {
89 let sk = Scalar::random(&mut UnwrapErr(SysRng));
90 let pk = (ProjectivePoint::GENERATOR * sk).to_affine();
91 (sk, pk)
92 }
93
94 #[test]
95 fn encrypt_decrypt_round_trips() {
96 let (sk, pk) = random_keypair();
97 let msg = (ProjectivePoint::GENERATOR * Scalar::from(42u32)).to_affine();
98 let ct = encrypt_point(&pk, &msg);
99 let recovered = decrypt_point(&sk, &ct).unwrap();
100 assert_eq!(recovered, msg);
101 }
102
103 #[test]
104 fn wrong_key_fails() {
105 let (_sk1, pk1) = random_keypair();
106 let (_, _pk2) = random_keypair();
107 let msg = (ProjectivePoint::GENERATOR * Scalar::from(42u32)).to_affine();
108 let ct = encrypt_point(&pk1, &msg);
109 let (sk2, _) = random_keypair();
111 let recovered = decrypt_point(&sk2, &ct).unwrap();
112 assert_ne!(recovered, msg);
113 }
114
115 #[test]
116 fn ciphertext_differs_per_encryption() {
117 let (_, pk) = random_keypair();
118 let msg = (ProjectivePoint::GENERATOR * Scalar::from(99u32)).to_affine();
119 let ct1 = encrypt_point(&pk, &msg);
120 let ct2 = encrypt_point(&pk, &msg);
121 assert_ne!(ct1.c1_hex, ct2.c1_hex);
122 }
123
124 #[test]
125 fn re_encrypt_preserves_format() {
126 let (sk, pk) = random_keypair();
127 let msg = (ProjectivePoint::GENERATOR * Scalar::from(7u32)).to_affine();
128 let ct = encrypt_point(&pk, &msg);
129 let rk = generate_rk(&sk, &pk);
130 let re_ct = re_encrypt(&rk, &ct);
131 assert!(!re_ct.c1_hex.is_empty());
133 assert!(!re_ct.c2_hex.is_empty());
134 }
135
136 #[test]
137 fn rk_carries_secret() {
138 let (sk, _) = random_keypair();
139 let rk = generate_rk(&sk, &(ProjectivePoint::GENERATOR).to_affine());
140 assert_eq!(rk.rk, sk);
141 }
142}