dcrypt_algorithms/ec/b283k/
field.rs1use crate::ec::b283k::constants::B283K_FIELD_ELEMENT_SIZE;
5use crate::error::{Error, Result};
6use subtle::{Choice, ConditionallySelectable};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct FieldElement(pub(crate) [u64; 5]);
11
12impl ConditionallySelectable for FieldElement {
13 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
14 let mut out = [0u64; 5];
15 for i in 0..5 {
16 out[i] = u64::conditional_select(&a.0[i], &b.0[i], choice);
17 }
18 FieldElement(out)
19 }
20}
21
22impl FieldElement {
23 const REDUCER: [u64; 5] = [1 << 12 | 1 << 7 | 1 << 5 | 1, 0, 0, 0, 0];
25
26 pub fn zero() -> Self {
28 FieldElement([0; 5])
29 }
30
31 pub fn one() -> Self {
33 FieldElement([1, 0, 0, 0, 0])
34 }
35
36 pub fn from_bytes(bytes: &[u8; B283K_FIELD_ELEMENT_SIZE]) -> Result<Self> {
40 let mut limbs = [0u64; 5];
41 limbs[4] = u64::from_be_bytes([0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3]]);
44 limbs[3] = u64::from_be_bytes(bytes[4..12].try_into().unwrap());
45 limbs[2] = u64::from_be_bytes(bytes[12..20].try_into().unwrap());
46 limbs[1] = u64::from_be_bytes(bytes[20..28].try_into().unwrap());
47 limbs[0] = u64::from_be_bytes(bytes[28..36].try_into().unwrap());
48
49 if limbs[4] & !((1u64 << 27) - 1) != 0 {
51 return Err(Error::param(
52 "FieldElement B283k",
53 "Value exceeds field size",
54 ));
55 }
56
57 Ok(FieldElement(limbs))
58 }
59
60 pub fn to_bytes(&self) -> [u8; B283K_FIELD_ELEMENT_SIZE] {
64 let mut bytes = [0u8; B283K_FIELD_ELEMENT_SIZE];
65 let top_limb_bytes = self.0[4].to_be_bytes();
68 bytes[0..4].copy_from_slice(&top_limb_bytes[4..]);
69 bytes[4..12].copy_from_slice(&self.0[3].to_be_bytes());
70 bytes[12..20].copy_from_slice(&self.0[2].to_be_bytes());
71 bytes[20..28].copy_from_slice(&self.0[1].to_be_bytes());
72 bytes[28..36].copy_from_slice(&self.0[0].to_be_bytes());
73 bytes
74 }
75
76 pub fn is_zero(&self) -> bool {
78 self.0.iter().all(|&l| l == 0)
79 }
80
81 pub fn add(&self, other: &Self) -> Self {
85 let mut res = [0u64; 5];
86 for (i, (a, b)) in self.0.iter().zip(other.0.iter()).enumerate() {
87 res[i] = a ^ b;
88 }
89 FieldElement(res)
90 }
91
92 pub fn mul(&self, other: &Self) -> Self {
96 let mut res = FieldElement::zero();
97 let mut a = *self;
98 let mut b = *other;
99
100 for _ in 0..283 {
101 if (b.0[0] & 1) == 1 {
102 res = res.add(&a);
103 }
104 b = b.shr1();
105 a = a.shl1();
106
107 if (a.0[4] >> 27) & 1 == 1 {
110 a = a.add(&FieldElement(Self::REDUCER));
112 a.0[4] &= (1u64 << 27) - 1;
114 }
115 }
116 res
117 }
118
119 pub fn square(&self) -> Self {
121 self.mul(self) }
123
124 pub fn invert(&self) -> Result<Self> {
129 if self.is_zero() {
130 return Err(Error::param("FieldElement B283k", "Inversion of zero"));
131 }
132 let mut res = *self;
134 for _ in 1..282 {
135 res = res.square();
136 res = res.mul(self);
137 }
138 res = res.square();
139 Ok(res)
140 }
141
142 pub fn sqrt(&self) -> Self {
146 let mut res = *self;
148 for _ in 0..282 {
149 res = res.square();
150 }
151 res
152 }
153
154 fn shl1(&self) -> Self {
156 let mut r = [0u64; 5];
157 r[0] = self.0[0] << 1;
158
159 for (i, (&curr, &prev)) in self.0[1..].iter().zip(self.0[..4].iter()).enumerate() {
161 r[i + 1] = (curr << 1) | (prev >> 63);
162 }
163
164 r[4] &= (1u64 << 28) - 1; FieldElement(r)
167 }
168
169 fn shr1(&self) -> Self {
171 let mut r = [0u64; 5];
172
173 for (i, (&curr, &next)) in self.0[..4].iter().zip(self.0[1..].iter()).enumerate() {
175 r[i] = (curr >> 1) | (next << 63);
176 }
177
178 r[4] = self.0[4] >> 1;
179 FieldElement(r)
180 }
181
182 pub fn trace(&self) -> u64 {
187 let mut res = *self;
188 let mut temp = *self;
189 for _ in 0..282 {
190 temp = temp.square();
191 res = res.add(&temp);
192 }
193 res.0[0] & 1
194 }
195}