dcrypt_algorithms/ec/b283k/
field.rs1use crate::ec::b283k::constants::B283K_FIELD_ELEMENT_SIZE;
5use crate::error::{Error, Result};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub struct FieldElement(pub(crate) [u64; 5]);
10
11impl FieldElement {
12 const REDUCER: [u64; 5] = [1 << 12 | 1 << 7 | 1 << 5 | 1, 0, 0, 0, 0];
14
15 pub fn zero() -> Self {
17 FieldElement([0; 5])
18 }
19
20 pub fn one() -> Self {
22 FieldElement([1, 0, 0, 0, 0])
23 }
24
25 pub fn from_bytes(bytes: &[u8; B283K_FIELD_ELEMENT_SIZE]) -> Result<Self> {
29 let mut limbs = [0u64; 5];
30 limbs[4] = u64::from_be_bytes([0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3]]);
33 limbs[3] = u64::from_be_bytes(bytes[4..12].try_into().unwrap());
34 limbs[2] = u64::from_be_bytes(bytes[12..20].try_into().unwrap());
35 limbs[1] = u64::from_be_bytes(bytes[20..28].try_into().unwrap());
36 limbs[0] = u64::from_be_bytes(bytes[28..36].try_into().unwrap());
37
38 if limbs[4] & !((1u64 << 27) - 1) != 0 {
40 return Err(Error::param(
41 "FieldElement B283k",
42 "Value exceeds field size",
43 ));
44 }
45
46 Ok(FieldElement(limbs))
47 }
48
49 pub fn to_bytes(&self) -> [u8; B283K_FIELD_ELEMENT_SIZE] {
53 let mut bytes = [0u8; B283K_FIELD_ELEMENT_SIZE];
54 let top_limb_bytes = self.0[4].to_be_bytes();
57 bytes[0..4].copy_from_slice(&top_limb_bytes[4..]);
58 bytes[4..12].copy_from_slice(&self.0[3].to_be_bytes());
59 bytes[12..20].copy_from_slice(&self.0[2].to_be_bytes());
60 bytes[20..28].copy_from_slice(&self.0[1].to_be_bytes());
61 bytes[28..36].copy_from_slice(&self.0[0].to_be_bytes());
62 bytes
63 }
64
65 pub fn is_zero(&self) -> bool {
67 self.0.iter().all(|&l| l == 0)
68 }
69
70 pub fn add(&self, other: &Self) -> Self {
74 let mut res = [0u64; 5];
75 for (i, (a, b)) in self.0.iter().zip(other.0.iter()).enumerate() {
76 res[i] = a ^ b;
77 }
78 FieldElement(res)
79 }
80
81 pub fn mul(&self, other: &Self) -> Self {
85 let mut res = FieldElement::zero();
86 let mut a = *self;
87 let mut b = *other;
88
89 for _ in 0..283 {
90 if (b.0[0] & 1) == 1 {
91 res = res.add(&a);
92 }
93 b = b.shr1();
94 a = a.shl1();
95
96 if (a.0[4] >> 27) & 1 == 1 {
99 a = a.add(&FieldElement(Self::REDUCER));
101 a.0[4] &= (1u64 << 27) - 1;
103 }
104 }
105 res
106 }
107
108 pub fn square(&self) -> Self {
110 self.mul(self) }
112
113 pub fn invert(&self) -> Result<Self> {
118 if self.is_zero() {
119 return Err(Error::param("FieldElement B283k", "Inversion of zero"));
120 }
121 let mut res = *self;
123 for _ in 1..282 {
124 res = res.square();
125 res = res.mul(self);
126 }
127 res = res.square();
128 Ok(res)
129 }
130
131 pub fn sqrt(&self) -> Self {
135 let mut res = *self;
137 for _ in 0..282 {
138 res = res.square();
139 }
140 res
141 }
142
143 fn shl1(&self) -> Self {
145 let mut r = [0u64; 5];
146 r[0] = self.0[0] << 1;
147
148 for (i, (&curr, &prev)) in self.0[1..].iter().zip(self.0[..4].iter()).enumerate() {
150 r[i + 1] = (curr << 1) | (prev >> 63);
151 }
152
153 r[4] &= (1u64 << 28) - 1; FieldElement(r)
156 }
157
158 fn shr1(&self) -> Self {
160 let mut r = [0u64; 5];
161
162 for (i, (&curr, &next)) in self.0[..4].iter().zip(self.0[1..].iter()).enumerate() {
164 r[i] = (curr >> 1) | (next << 63);
165 }
166
167 r[4] = self.0[4] >> 1;
168 FieldElement(r)
169 }
170
171 pub fn trace(&self) -> u64 {
176 let mut res = *self;
177 let mut temp = *self;
178 for _ in 0..282 {
179 temp = temp.square();
180 res = res.add(&temp);
181 }
182 res.0[0] & 1
183 }
184}