Skip to main content

ope_simplified/
ope.rs

1use std::cell::RefCell;
2
3use crate::stats::{sample_hgd, sample_uniform};
4use hmac::Hmac;
5use sha2::Sha256;
6
7pub type HmacSha256 = Hmac<Sha256>;
8
9pub const DEFAULT_IN_RANGE_START: i32 = 0;
10pub const DEFAULT_IN_RANGE_END: i32 = 2i32.pow(15) - 1;
11pub const DEFAULT_OUT_RANGE_START: i32 = 0;
12pub const DEFAULT_OUT_RANGE_END: i32 = 2i32.pow(15) - 1;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum OpeError {
16    InvalidRangeLimitsError,
17    InvalidCiphertextError,
18    OutOfRangeError,
19    InvalidCoinError,
20    NotEnoughCoinsError,
21}
22
23#[derive(Debug, Clone, PartialEq)]
24pub struct ValueRange {
25    pub start: i32,
26    pub end: i32,
27}
28
29impl ValueRange {
30    pub fn new(start: i32, end: i32) -> Result<Self, OpeError> {
31        if start > end {
32            return Err(OpeError::InvalidRangeLimitsError);
33        }
34        Ok(ValueRange { start, end })
35    }
36
37    pub fn size(&self) -> i32 {
38        self.end - self.start + 1
39    }
40
41    pub fn contains(&self, number: i32) -> bool {
42        self.start <= number && number <= self.end
43    }
44}
45
46pub struct Ope {
47    pub key: Vec<u8>,
48    pub in_range: ValueRange,
49    pub out_range: ValueRange,
50}
51
52impl Ope {
53    pub fn new(
54        key: &[u8],
55        in_range: Option<ValueRange>,
56        out_range: Option<ValueRange>,
57    ) -> Result<Self, OpeError> {
58        let in_range = in_range
59            .unwrap_or(ValueRange::new(DEFAULT_IN_RANGE_START, DEFAULT_IN_RANGE_END)?);
60        let out_range = out_range
61            .unwrap_or(ValueRange::new(DEFAULT_OUT_RANGE_START, DEFAULT_OUT_RANGE_END)?);
62
63        if in_range.size() > out_range.size() {
64            return Err(OpeError::OutOfRangeError);
65        }
66
67        Ok(Ope { key: key.to_vec(), in_range, out_range })
68    }
69
70    pub fn encrypt(&self, plaintext: i32) -> Result<i32, OpeError> {
71        if !self.in_range.contains(plaintext) {
72            return Err(OpeError::OutOfRangeError);
73        }
74        self.encrypt_recursive(plaintext, self.in_range.clone(), self.out_range.clone())
75    }
76
77    fn encrypt_recursive(
78        &self,
79        plaintext: i32,
80        mut in_range: ValueRange,
81        mut out_range: ValueRange,
82    ) -> Result<i32, OpeError> {
83        let in_size = in_range.size();
84        let out_size = out_range.size();
85        let in_edge = in_range.start.wrapping_sub(1);
86        let out_edge = out_range.start.wrapping_sub(1);
87        let mid = out_edge + ((out_size + 1) / 2);
88
89        if in_range.size() == 1 {
90            let coins = RefCell::new(self.tape_gen(plaintext));
91            let ciphertext = sample_uniform(out_range, Box::new(coins));
92            return Ok(ciphertext);
93        }
94
95        let coins = self.tape_gen(mid);
96        let x = sample_hgd(in_range, out_range, mid, Box::new(coins));
97
98        if plaintext <= x {
99            in_range = ValueRange::new(in_edge + 1, x)?;
100            out_range = ValueRange::new(out_edge + 1, mid)?;
101        } else {
102            in_range = ValueRange::new(x + 1, in_edge + in_size)?;
103            out_range = ValueRange::new(mid + 1, out_edge + out_size)?;
104        }
105        self.encrypt_recursive(plaintext, in_range, out_range)
106    }
107
108    pub fn decrypt(&self, ciphertext: i32) -> Result<i32, OpeError> {
109        if !self.out_range.contains(ciphertext) {
110            return Err(OpeError::OutOfRangeError);
111        }
112        self.decrypt_recursive(ciphertext, self.in_range.clone(), self.out_range.clone())
113    }
114
115    fn decrypt_recursive(
116        &self,
117        ciphertext: i32,
118        mut in_range: ValueRange,
119        mut out_range: ValueRange,
120    ) -> Result<i32, OpeError> {
121        let in_size = in_range.size();
122        let out_size = out_range.size();
123        let in_edge = in_range.start.wrapping_sub(1);
124        let out_edge = out_range.start.wrapping_sub(1);
125        let mid = out_edge + ((out_size + 1) / 2);
126
127        if out_range.size() == 1 {
128            let coins = RefCell::new(self.tape_gen(ciphertext));
129            let plaintext = sample_uniform(in_range, Box::new(coins)); // sample_uniform needs to be implemented
130            return Ok(plaintext);
131        }
132
133        let coins = self.tape_gen(mid);
134        let x = sample_hgd(in_range, out_range, mid, Box::new(coins)); // sample_hgd needs to be implemented
135
136        if ciphertext <= mid {
137            out_range = ValueRange::new(out_edge + 1, mid)?;
138            in_range = ValueRange::new(in_edge + 1, x)?;
139        } else {
140            out_range = ValueRange::new(mid + 1, out_edge + out_size)?;
141            in_range = ValueRange::new(x + 1, in_edge + in_size)?;
142        }
143        self.decrypt_recursive(ciphertext, in_range, out_range)
144    }
145
146    fn tape_gen(&self, data: i32) -> impl Iterator<Item = bool> {
147        let data_bytes = data.to_le_bytes();
148        let mut bits = Vec::new();
149
150        for &byte in data_bytes.iter() {
151            for i in 0..8 {
152                bits.push((byte >> i) & 1 == 1);
153            }
154        }
155
156        bits.into_iter()
157    }
158}