pub struct RingElem { /* private fields */ }Expand description
Canonical element of R_q = Z_q[x] / (f(x)).
Each operation applies the corresponding polynomial arithmetic and then reduces modulo f(x).
Implementations§
Source§impl RingElem
impl RingElem
Sourcepub fn params(&self) -> &Params
pub fn params(&self) -> &Params
Returns the validated parameter set that defines this element’s ring.
Examples found in repository?
More examples
examples/common/codec.rs (line 137)
132pub fn decode_message_scaled_bits_example(
133 element: &RingElem,
134 output_len_bytes: usize,
135) -> Result<Vec<u8>, CodecError> {
136 // Decode limit follows the same bit-capacity convention used at encode time.
137 let capacity_bits = element.params().max_degree();
138 let requested_bits = output_len_bytes.saturating_mul(8);
139 if requested_bits > capacity_bits {
140 return Err(CodecError::DecodeLengthTooLong {
141 requested_bits,
142 capacity_bits,
143 });
144 }
145
146 let q = element.params().modulus();
147 // Threshold window near middle of modulus range.
148 // Values in `[q/4, 3q/4)` decode to 1; others decode to 0.
149 let lower = q / 4;
150 let upper = (3 * q) / 4;
151
152 let mut out = vec![0_u8; output_len_bytes];
153 for bit_index in 0..requested_bits {
154 let coeff = element.coefficients()[bit_index];
155 let bit = coeff >= lower && coeff < upper;
156 if bit {
157 // Restore little-endian bit position.
158 out[bit_index / 8] |= 1_u8 << (bit_index % 8);
159 }
160 }
161
162 Ok(out)
163}
164
165/// Compresses one coefficient into `bits` bits.
166pub fn compress_coefficient_example(value: u64, modulus: u64, bits: u8) -> Result<u16, CodecError> {
167 validate_compression_bits(bits)?;
168
169 // Quantization levels = 2^bits.
170 let levels = 1_u128 << bits;
171 let q = modulus as u128;
172 let v = (value % modulus) as u128;
173
174 // Rounded scaling from `[0, q)` into `[0, 2^bits)`.
175 let compressed = ((v * levels + (q / 2)) / q) % levels;
176 Ok(compressed as u16)
177}
178
179/// Decompresses one `bits`-bit coefficient back into `Z_q`.
180pub fn decompress_coefficient_example(
181 compressed: u16,
182 modulus: u64,
183 bits: u8,
184) -> Result<u64, CodecError> {
185 validate_compression_bits(bits)?;
186
187 let levels = 1_u128 << bits;
188 let q = modulus as u128;
189 let c = (compressed as u128) % levels;
190
191 // Rounded inverse scaling from `[0, 2^bits)` back into `[0, q)`.
192 let decompressed = (c * q + (levels / 2)) / levels;
193 Ok((decompressed % q) as u64)
194}
195
196/// Compresses all coefficients of a ring element into `bits` bits each.
197pub fn compress_ring_elem_example(element: &RingElem, bits: u8) -> Result<Vec<u16>, CodecError> {
198 validate_compression_bits(bits)?;
199
200 let q = element.params().modulus();
201 // Compress each coefficient independently.
202 let mut packed = Vec::with_capacity(element.coefficients().len());
203 for &coeff in element.coefficients() {
204 packed.push(compress_coefficient_example(coeff, q, bits)?);
205 }
206 Ok(packed)
207}Sourcepub fn polynomial(&self) -> &Polynomial
pub fn polynomial(&self) -> &Polynomial
Returns the underlying canonical polynomial representative.
Sourcepub fn into_polynomial(self) -> Polynomial
pub fn into_polynomial(self) -> Polynomial
Consumes and returns the underlying polynomial representative.
Sourcepub fn coefficients(&self) -> &[u64]
pub fn coefficients(&self) -> &[u64]
Returns the dense coefficient slice of the canonical representative.
Examples found in repository?
examples/common/codec.rs (line 154)
132pub fn decode_message_scaled_bits_example(
133 element: &RingElem,
134 output_len_bytes: usize,
135) -> Result<Vec<u8>, CodecError> {
136 // Decode limit follows the same bit-capacity convention used at encode time.
137 let capacity_bits = element.params().max_degree();
138 let requested_bits = output_len_bytes.saturating_mul(8);
139 if requested_bits > capacity_bits {
140 return Err(CodecError::DecodeLengthTooLong {
141 requested_bits,
142 capacity_bits,
143 });
144 }
145
146 let q = element.params().modulus();
147 // Threshold window near middle of modulus range.
148 // Values in `[q/4, 3q/4)` decode to 1; others decode to 0.
149 let lower = q / 4;
150 let upper = (3 * q) / 4;
151
152 let mut out = vec![0_u8; output_len_bytes];
153 for bit_index in 0..requested_bits {
154 let coeff = element.coefficients()[bit_index];
155 let bit = coeff >= lower && coeff < upper;
156 if bit {
157 // Restore little-endian bit position.
158 out[bit_index / 8] |= 1_u8 << (bit_index % 8);
159 }
160 }
161
162 Ok(out)
163}
164
165/// Compresses one coefficient into `bits` bits.
166pub fn compress_coefficient_example(value: u64, modulus: u64, bits: u8) -> Result<u16, CodecError> {
167 validate_compression_bits(bits)?;
168
169 // Quantization levels = 2^bits.
170 let levels = 1_u128 << bits;
171 let q = modulus as u128;
172 let v = (value % modulus) as u128;
173
174 // Rounded scaling from `[0, q)` into `[0, 2^bits)`.
175 let compressed = ((v * levels + (q / 2)) / q) % levels;
176 Ok(compressed as u16)
177}
178
179/// Decompresses one `bits`-bit coefficient back into `Z_q`.
180pub fn decompress_coefficient_example(
181 compressed: u16,
182 modulus: u64,
183 bits: u8,
184) -> Result<u64, CodecError> {
185 validate_compression_bits(bits)?;
186
187 let levels = 1_u128 << bits;
188 let q = modulus as u128;
189 let c = (compressed as u128) % levels;
190
191 // Rounded inverse scaling from `[0, 2^bits)` back into `[0, q)`.
192 let decompressed = (c * q + (levels / 2)) / levels;
193 Ok((decompressed % q) as u64)
194}
195
196/// Compresses all coefficients of a ring element into `bits` bits each.
197pub fn compress_ring_elem_example(element: &RingElem, bits: u8) -> Result<Vec<u16>, CodecError> {
198 validate_compression_bits(bits)?;
199
200 let q = element.params().modulus();
201 // Compress each coefficient independently.
202 let mut packed = Vec::with_capacity(element.coefficients().len());
203 for &coeff in element.coefficients() {
204 packed.push(compress_coefficient_example(coeff, q, bits)?);
205 }
206 Ok(packed)
207}Sourcepub fn trimmed_coefficients(&self) -> Vec<u64>
pub fn trimmed_coefficients(&self) -> Vec<u64>
Returns coefficients trimmed to the actual degree.
Sourcepub fn degree(&self) -> Option<usize>
pub fn degree(&self) -> Option<usize>
Returns the representative’s polynomial degree.
Examples found in repository?
examples/helpers_codec.rs (line 71)
42fn main() {
43 // Use a power-of-two cyclotomic-style modulus polynomial `x^32 + 1`.
44 let mut modulus_poly = vec![0_u64; 32 + 1];
45 modulus_poly[0] = 1;
46 modulus_poly[32] = 1;
47 // Create validated context (n=32, q=998244353, primitive root=3).
48 let ctx =
49 RingContext::from_parts(32, 998_244_353, &modulus_poly, 3).expect("context should build");
50
51 // Message to encode. Each bit maps into one coefficient slot.
52 let message = b"Rust";
53 // Encode bytes -> ring element with coefficients in `{0, floor((q+1)/2)}`.
54 let encoded =
55 encode_message_scaled_bits_example(&ctx, message).expect("message encoding should work");
56 // Decode ring element -> bytes (threshold decoding in coefficient domain).
57 let decoded = decode_message_scaled_bits_example(&encoded, message.len())
58 .expect("message decoding should work");
59 // End-to-end correctness check.
60 assert_eq!(decoded, message);
61
62 // Quantize coefficients to 11-bit buckets.
63 let compressed = compress_ring_elem_example(&encoded, 11).expect("compression should work");
64 // Lift quantized coefficients back into `Z_q`.
65 let decompressed =
66 decompress_ring_elem_example(&ctx, &compressed, 11).expect("decompression should work");
67
68 // Print summary values to inspect behavior quickly.
69 println!("decoded_message={:?}", String::from_utf8_lossy(&decoded));
70 println!("compressed_coeffs={}", compressed.len());
71 println!("decompressed_degree={:?}", decompressed.degree());
72}More examples
examples/helpers_sampling.rs (line 128)
99fn main() {
100 // Configure modulus polynomial `x^16 + 1`.
101 //
102 // We allocate `max_degree + 1` coefficients and set:
103 // - constant term: 1
104 // - x^16 term: 1
105 // - all intermediate terms: 0
106 let mut modulus_poly = vec![0_u64; 16 + 1];
107 modulus_poly[0] = 1;
108 modulus_poly[16] = 1;
109 // Build validated ring context with NTT-friendly modulus and primitive root.
110 let ctx =
111 RingContext::from_parts(16, 998_244_353, &modulus_poly, 3).expect("context should build");
112
113 // Deterministic seed makes this executable reproducible.
114 let mut rng = ExampleRng::new(0xA11C_E123_0000_0001);
115
116 // Uniform sample in `R_q`: every coefficient is sampled independently in `[0, q)`.
117 let uniform =
118 sample_uniform_poly_example(&ctx, &mut rng).expect("uniform sampling should work");
119 // Centered-binomial sample: each coefficient is small noise around 0.
120 let cbd = sample_cbd_poly_example(&ctx, 3, &mut rng).expect("CBD sampling should work");
121 // Gaussian-like sample from Box-Muller + integer rounding.
122 let gaussian =
123 sample_discrete_gaussian_poly_example(&ctx, 2.5, &mut rng).expect("gaussian should work");
124 // Raw integer rejection sample in `[0, 1000)`.
125 let below = sample_rejection_u64_below_example(1_000, &mut rng).expect("rejection should work");
126
127 // Print concise observable properties so this can be used as a smoke run.
128 println!("uniform_degree={:?}", uniform.degree());
129 println!("cbd_degree={:?}", cbd.degree());
130 println!("gaussian_degree={:?}", gaussian.degree());
131 println!("sample_below_1000={below}");
132}Sourcepub fn add(&self, rhs: &Self) -> Result<Self, PolynomialError>
pub fn add(&self, rhs: &Self) -> Result<Self, PolynomialError>
Adds two ring elements.
Examples found in repository?
examples/common/pke.rs (line 118)
105pub fn keygen_example<R: CryptoRng>(
106 ctx: &RingContext,
107 noise_eta: u8,
108 rng: &mut R,
109) -> Result<(ExamplePublicKey, ExampleSecretKey), ExamplePkeError> {
110 // Public random polynomial.
111 let a = sample_uniform_poly_example(ctx, rng)?;
112 // Secret small-noise polynomial.
113 let s = sample_cbd_poly_example(ctx, noise_eta, rng)?;
114 // Public error polynomial.
115 let e = sample_cbd_poly_example(ctx, noise_eta, rng)?;
116
117 // RLWE public relation: b = a*s + e.
118 let b = a.mul(&s)?.add(&e)?;
119
120 Ok((ExamplePublicKey { a, b }, ExampleSecretKey { s }))
121}
122
123/// Encrypts a byte message using the example key.
124///
125/// The message is encoded using scaled bits from [`encode_message_scaled_bits_example`].
126pub fn encrypt_example<R: CryptoRng>(
127 ctx: &RingContext,
128 public_key: &ExamplePublicKey,
129 message: &[u8],
130 noise_eta: u8,
131 rng: &mut R,
132) -> Result<ExampleCiphertext, ExamplePkeError> {
133 // Ensure all key elements come from the same validated parameter set.
134 ensure_element_matches_context(ctx, &public_key.a)?;
135 ensure_element_matches_context(ctx, &public_key.b)?;
136
137 // Encode message bits into ring element form.
138 let m = encode_message_scaled_bits_example(ctx, message)?;
139 // Fresh encryption randomness + masking errors.
140 let r = sample_cbd_poly_example(ctx, noise_eta, rng)?;
141 let e1 = sample_cbd_poly_example(ctx, noise_eta, rng)?;
142 let e2 = sample_cbd_poly_example(ctx, noise_eta, rng)?;
143
144 // RLWE encryption equations:
145 // u = a*r + e1
146 // v = b*r + e2 + m
147 let u = public_key.a.mul(&r)?.add(&e1)?;
148 let v = public_key.b.mul(&r)?.add(&e2)?.add(&m)?;
149
150 Ok(ExampleCiphertext { u, v })
151}Sourcepub fn sub(&self, rhs: &Self) -> Result<Self, PolynomialError>
pub fn sub(&self, rhs: &Self) -> Result<Self, PolynomialError>
Subtracts two ring elements.
Examples found in repository?
examples/common/pke.rs (line 169)
154pub fn decrypt_example(
155 ctx: &RingContext,
156 secret_key: &ExampleSecretKey,
157 ciphertext: &ExampleCiphertext,
158 output_len_bytes: usize,
159) -> Result<Vec<u8>, ExamplePkeError> {
160 // Context checks prevent cross-parameter misuse.
161 ensure_element_matches_context(ctx, &secret_key.s)?;
162 ensure_element_matches_context(ctx, &ciphertext.u)?;
163 ensure_element_matches_context(ctx, &ciphertext.v)?;
164
165 // Recover encoded message:
166 // v - s*u = (a*s + e)r + e2 + m - s(a*r + e1)
167 // = m + (e*r + e2 - s*e1)
168 // Small noise lets threshold decoder recover bits.
169 let recovered = ciphertext.v.sub(&secret_key.s.mul(&ciphertext.u)?)?;
170 Ok(decode_message_scaled_bits_example(
171 &recovered,
172 output_len_bytes,
173 )?)
174}Sourcepub fn mul(&self, rhs: &Self) -> Result<Self, PolynomialError>
pub fn mul(&self, rhs: &Self) -> Result<Self, PolynomialError>
Multiplies two ring elements.
Examples found in repository?
examples/common/pke.rs (line 118)
105pub fn keygen_example<R: CryptoRng>(
106 ctx: &RingContext,
107 noise_eta: u8,
108 rng: &mut R,
109) -> Result<(ExamplePublicKey, ExampleSecretKey), ExamplePkeError> {
110 // Public random polynomial.
111 let a = sample_uniform_poly_example(ctx, rng)?;
112 // Secret small-noise polynomial.
113 let s = sample_cbd_poly_example(ctx, noise_eta, rng)?;
114 // Public error polynomial.
115 let e = sample_cbd_poly_example(ctx, noise_eta, rng)?;
116
117 // RLWE public relation: b = a*s + e.
118 let b = a.mul(&s)?.add(&e)?;
119
120 Ok((ExamplePublicKey { a, b }, ExampleSecretKey { s }))
121}
122
123/// Encrypts a byte message using the example key.
124///
125/// The message is encoded using scaled bits from [`encode_message_scaled_bits_example`].
126pub fn encrypt_example<R: CryptoRng>(
127 ctx: &RingContext,
128 public_key: &ExamplePublicKey,
129 message: &[u8],
130 noise_eta: u8,
131 rng: &mut R,
132) -> Result<ExampleCiphertext, ExamplePkeError> {
133 // Ensure all key elements come from the same validated parameter set.
134 ensure_element_matches_context(ctx, &public_key.a)?;
135 ensure_element_matches_context(ctx, &public_key.b)?;
136
137 // Encode message bits into ring element form.
138 let m = encode_message_scaled_bits_example(ctx, message)?;
139 // Fresh encryption randomness + masking errors.
140 let r = sample_cbd_poly_example(ctx, noise_eta, rng)?;
141 let e1 = sample_cbd_poly_example(ctx, noise_eta, rng)?;
142 let e2 = sample_cbd_poly_example(ctx, noise_eta, rng)?;
143
144 // RLWE encryption equations:
145 // u = a*r + e1
146 // v = b*r + e2 + m
147 let u = public_key.a.mul(&r)?.add(&e1)?;
148 let v = public_key.b.mul(&r)?.add(&e2)?.add(&m)?;
149
150 Ok(ExampleCiphertext { u, v })
151}
152
153/// Decrypts an example ciphertext and decodes the requested number of output bytes.
154pub fn decrypt_example(
155 ctx: &RingContext,
156 secret_key: &ExampleSecretKey,
157 ciphertext: &ExampleCiphertext,
158 output_len_bytes: usize,
159) -> Result<Vec<u8>, ExamplePkeError> {
160 // Context checks prevent cross-parameter misuse.
161 ensure_element_matches_context(ctx, &secret_key.s)?;
162 ensure_element_matches_context(ctx, &ciphertext.u)?;
163 ensure_element_matches_context(ctx, &ciphertext.v)?;
164
165 // Recover encoded message:
166 // v - s*u = (a*s + e)r + e2 + m - s(a*r + e1)
167 // = m + (e*r + e2 - s*e1)
168 // Small noise lets threshold decoder recover bits.
169 let recovered = ciphertext.v.sub(&secret_key.s.mul(&ciphertext.u)?)?;
170 Ok(decode_message_scaled_bits_example(
171 &recovered,
172 output_len_bytes,
173 )?)
174}Sourcepub fn scalar_mul(&self, scalar: u64) -> Self
pub fn scalar_mul(&self, scalar: u64) -> Self
Multiplies by a scalar in Z_q.
Trait Implementations§
impl Eq for RingElem
impl StructuralPartialEq for RingElem
Auto Trait Implementations§
impl Freeze for RingElem
impl RefUnwindSafe for RingElem
impl Send for RingElem
impl Sync for RingElem
impl Unpin for RingElem
impl UnwindSafe for RingElem
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more