Pull to_bytes() into FieldElement.
This commit is contained in:
@@ -76,6 +76,85 @@ impl FieldElement
|
|||||||
h4 as i32, h5 as i32, h6 as i32, h7 as i32,
|
h4 as i32, h5 as i32, h6 as i32, h7 as i32,
|
||||||
h8 as i32, h9 as i32] }
|
h8 as i32, h9 as i32] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut h0 = self.value[0];
|
||||||
|
let mut h1 = self.value[1];
|
||||||
|
let mut h2 = self.value[2];
|
||||||
|
let mut h3 = self.value[3];
|
||||||
|
let mut h4 = self.value[4];
|
||||||
|
let mut h5 = self.value[5];
|
||||||
|
let mut h6 = self.value[6];
|
||||||
|
let mut h7 = self.value[7];
|
||||||
|
let mut h8 = self.value[8];
|
||||||
|
let mut h9 = self.value[9];
|
||||||
|
|
||||||
|
let mut q = (19 * h9 + ((1i32) << 24)) >> 25;
|
||||||
|
q = (h0 + q) >> 26;
|
||||||
|
q = (h1 + q) >> 25;
|
||||||
|
q = (h2 + q) >> 26;
|
||||||
|
q = (h3 + q) >> 25;
|
||||||
|
q = (h4 + q) >> 26;
|
||||||
|
q = (h5 + q) >> 25;
|
||||||
|
q = (h6 + q) >> 26;
|
||||||
|
q = (h7 + q) >> 25;
|
||||||
|
q = (h8 + q) >> 26;
|
||||||
|
q = (h9 + q) >> 25;
|
||||||
|
|
||||||
|
/* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
|
||||||
|
h0 += 19 * q;
|
||||||
|
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
|
||||||
|
h1 += h0 >> 26; h0 &= KBOTTOM_26BITS as i32;
|
||||||
|
h2 += h1 >> 25; h1 &= KBOTTOM_25BITS as i32;
|
||||||
|
h3 += h2 >> 26; h2 &= KBOTTOM_26BITS as i32;
|
||||||
|
h4 += h3 >> 25; h3 &= KBOTTOM_25BITS as i32;
|
||||||
|
h5 += h4 >> 26; h4 &= KBOTTOM_26BITS as i32;
|
||||||
|
h6 += h5 >> 25; h5 &= KBOTTOM_25BITS as i32;
|
||||||
|
h7 += h6 >> 26; h6 &= KBOTTOM_26BITS as i32;
|
||||||
|
h8 += h7 >> 25; h7 &= KBOTTOM_25BITS as i32;
|
||||||
|
h9 += h8 >> 26; h8 &= KBOTTOM_26BITS as i32;
|
||||||
|
h9 &= KBOTTOM_25BITS as i32;
|
||||||
|
/* h10 = carry9 */
|
||||||
|
|
||||||
|
/* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
|
||||||
|
* Have h0+...+2^230 h9 between 0 and 2^255-1;
|
||||||
|
* evidently 2^255 h10-2^255 q = 0.
|
||||||
|
* Goal: Output h0+...+2^230 h9. */
|
||||||
|
vec![ (h0 >> 0) as u8,
|
||||||
|
(h0 >> 8) as u8,
|
||||||
|
(h0 >> 16) as u8,
|
||||||
|
((h0 >> 24) | (((h1 as u32) << 2) as i32)) as u8,
|
||||||
|
(h1 >> 6) as u8,
|
||||||
|
(h1 >> 14) as u8,
|
||||||
|
((h1 >> 22) | (((h2 as u32) << 3) as i32)) as u8,
|
||||||
|
(h2 >> 5) as u8,
|
||||||
|
(h2 >> 13) as u8,
|
||||||
|
((h2 >> 21) | (((h3 as u32) << 5) as i32)) as u8,
|
||||||
|
(h3 >> 3) as u8,
|
||||||
|
(h3 >> 11) as u8,
|
||||||
|
((h3 >> 19) | (((h4 as u32) << 6) as i32)) as u8,
|
||||||
|
(h4 >> 2) as u8,
|
||||||
|
(h4 >> 10) as u8,
|
||||||
|
(h4 >> 18) as u8,
|
||||||
|
(h5 >> 0) as u8,
|
||||||
|
(h5 >> 8) as u8,
|
||||||
|
(h5 >> 16) as u8,
|
||||||
|
((h5 >> 24) | (((h6 as u32) << 1) as i32)) as u8,
|
||||||
|
(h6 >> 7) as u8,
|
||||||
|
(h6 >> 15) as u8,
|
||||||
|
((h6 >> 23) | (((h7 as u32) << 3) as i32)) as u8,
|
||||||
|
(h7 >> 5) as u8,
|
||||||
|
(h7 >> 13) as u8,
|
||||||
|
((h7 >> 21) | (((h8 as u32) << 4) as i32)) as u8,
|
||||||
|
(h8 >> 4) as u8,
|
||||||
|
(h8 >> 12) as u8,
|
||||||
|
((h8 >> 20) | (((h9 as u32) << 6) as i32)) as u8,
|
||||||
|
(h9 >> 2) as u8,
|
||||||
|
(h9 >> 10) as u8,
|
||||||
|
(h9 >> 18) as u8
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const KBOTTOM_25BITS : i64 = 0x1ffffffi64;
|
pub const KBOTTOM_25BITS : i64 = 0x1ffffffi64;
|
||||||
@@ -111,85 +190,6 @@ fn loads() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fe_tobytes(s: &mut [u8], h: &FieldElement)
|
|
||||||
{
|
|
||||||
assert!(s.len() >= 32);
|
|
||||||
let mut h0 = h.value[0];
|
|
||||||
let mut h1 = h.value[1];
|
|
||||||
let mut h2 = h.value[2];
|
|
||||||
let mut h3 = h.value[3];
|
|
||||||
let mut h4 = h.value[4];
|
|
||||||
let mut h5 = h.value[5];
|
|
||||||
let mut h6 = h.value[6];
|
|
||||||
let mut h7 = h.value[7];
|
|
||||||
let mut h8 = h.value[8];
|
|
||||||
let mut h9 = h.value[9];
|
|
||||||
|
|
||||||
let mut q = (19 * h9 + ((1i32) << 24)) >> 25;
|
|
||||||
q = (h0 + q) >> 26;
|
|
||||||
q = (h1 + q) >> 25;
|
|
||||||
q = (h2 + q) >> 26;
|
|
||||||
q = (h3 + q) >> 25;
|
|
||||||
q = (h4 + q) >> 26;
|
|
||||||
q = (h5 + q) >> 25;
|
|
||||||
q = (h6 + q) >> 26;
|
|
||||||
q = (h7 + q) >> 25;
|
|
||||||
q = (h8 + q) >> 26;
|
|
||||||
q = (h9 + q) >> 25;
|
|
||||||
|
|
||||||
/* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
|
|
||||||
h0 += 19 * q;
|
|
||||||
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
|
|
||||||
h1 += h0 >> 26; h0 &= KBOTTOM_26BITS as i32;
|
|
||||||
h2 += h1 >> 25; h1 &= KBOTTOM_25BITS as i32;
|
|
||||||
h3 += h2 >> 26; h2 &= KBOTTOM_26BITS as i32;
|
|
||||||
h4 += h3 >> 25; h3 &= KBOTTOM_25BITS as i32;
|
|
||||||
h5 += h4 >> 26; h4 &= KBOTTOM_26BITS as i32;
|
|
||||||
h6 += h5 >> 25; h5 &= KBOTTOM_25BITS as i32;
|
|
||||||
h7 += h6 >> 26; h6 &= KBOTTOM_26BITS as i32;
|
|
||||||
h8 += h7 >> 25; h7 &= KBOTTOM_25BITS as i32;
|
|
||||||
h9 += h8 >> 26; h8 &= KBOTTOM_26BITS as i32;
|
|
||||||
h9 &= KBOTTOM_25BITS as i32;
|
|
||||||
/* h10 = carry9 */
|
|
||||||
|
|
||||||
/* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
|
|
||||||
* Have h0+...+2^230 h9 between 0 and 2^255-1;
|
|
||||||
* evidently 2^255 h10-2^255 q = 0.
|
|
||||||
* Goal: Output h0+...+2^230 h9. */
|
|
||||||
s[0] = (h0 >> 0) as u8;
|
|
||||||
s[1] = (h0 >> 8) as u8;
|
|
||||||
s[2] = (h0 >> 16) as u8;
|
|
||||||
s[3] = ((h0 >> 24) | (((h1 as u32) << 2) as i32)) as u8;
|
|
||||||
s[4] = (h1 >> 6) as u8;
|
|
||||||
s[5] = (h1 >> 14) as u8;
|
|
||||||
s[6] = ((h1 >> 22) | (((h2 as u32) << 3) as i32)) as u8;
|
|
||||||
s[7] = (h2 >> 5) as u8;
|
|
||||||
s[8] = (h2 >> 13) as u8;
|
|
||||||
s[9] = ((h2 >> 21) | (((h3 as u32) << 5) as i32)) as u8;
|
|
||||||
s[10] = (h3 >> 3) as u8;
|
|
||||||
s[11] = (h3 >> 11) as u8;
|
|
||||||
s[12] = ((h3 >> 19) | (((h4 as u32) << 6) as i32)) as u8;
|
|
||||||
s[13] = (h4 >> 2) as u8;
|
|
||||||
s[14] = (h4 >> 10) as u8;
|
|
||||||
s[15] = (h4 >> 18) as u8;
|
|
||||||
s[16] = (h5 >> 0) as u8;
|
|
||||||
s[17] = (h5 >> 8) as u8;
|
|
||||||
s[18] = (h5 >> 16) as u8;
|
|
||||||
s[19] = ((h5 >> 24) | (((h6 as u32) << 1) as i32)) as u8;
|
|
||||||
s[20] = (h6 >> 7) as u8;
|
|
||||||
s[21] = (h6 >> 15) as u8;
|
|
||||||
s[22] = ((h6 >> 23) | (((h7 as u32) << 3) as i32)) as u8;
|
|
||||||
s[23] = (h7 >> 5) as u8;
|
|
||||||
s[24] = (h7 >> 13) as u8;
|
|
||||||
s[25] = ((h7 >> 21) | (((h8 as u32) << 4) as i32)) as u8;
|
|
||||||
s[26] = (h8 >> 4) as u8;
|
|
||||||
s[27] = (h8 >> 12) as u8;
|
|
||||||
s[28] = ((h8 >> 20) | (((h9 as u32) << 6) as i32)) as u8;
|
|
||||||
s[29] = (h9 >> 2) as u8;
|
|
||||||
s[30] = (h9 >> 10) as u8;
|
|
||||||
s[31] = (h9 >> 18) as u8;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
#[test]
|
||||||
fn from_to_bytes() {
|
fn from_to_bytes() {
|
||||||
@@ -204,9 +204,8 @@ fn from_to_bytes() {
|
|||||||
let mut cursor = Cursor::new(bbytes);
|
let mut cursor = Cursor::new(bbytes);
|
||||||
cursor.read_i32_into::<NativeEndian>(&mut target.value).unwrap();
|
cursor.read_i32_into::<NativeEndian>(&mut target.value).unwrap();
|
||||||
assert_eq!(e, target, "from bytes");
|
assert_eq!(e, target, "from bytes");
|
||||||
let mut bytes = [0; 32];
|
let bytes = e.to_bytes();
|
||||||
fe_tobytes(&mut bytes, &e);
|
assert_eq!(&bytes, abytes, "to bytes");
|
||||||
assert_eq!(&bytes.to_vec(), abytes, "to bytes");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,8 +242,7 @@ quickcheck! {
|
|||||||
// this is somewhat self referential, given the definition of arbitrary,
|
// this is somewhat self referential, given the definition of arbitrary,
|
||||||
// but more testing is more good
|
// but more testing is more good
|
||||||
fn from_to_bytes_roundtrip(e: ValidFieldElement) -> bool {
|
fn from_to_bytes_roundtrip(e: ValidFieldElement) -> bool {
|
||||||
let mut bytes = [0; 32];
|
let bytes = e.values.to_bytes();
|
||||||
fe_tobytes(&mut bytes, &e.values);
|
|
||||||
let trans = FieldElement::from_bytes(&bytes);
|
let trans = FieldElement::from_bytes(&bytes);
|
||||||
trans == e.values
|
trans == e.values
|
||||||
}
|
}
|
||||||
@@ -822,9 +820,8 @@ fn cmov() {
|
|||||||
|
|
||||||
pub fn fe_isnonzero(f: &FieldElement) -> bool
|
pub fn fe_isnonzero(f: &FieldElement) -> bool
|
||||||
{
|
{
|
||||||
let mut s = [0; 32];
|
let s = f.to_bytes();
|
||||||
let mut res = false;
|
let mut res = false;
|
||||||
fe_tobytes(&mut s, &f);
|
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
res |= s[i] != 0;
|
res |= s[i] != 0;
|
||||||
}
|
}
|
||||||
@@ -833,8 +830,7 @@ pub fn fe_isnonzero(f: &FieldElement) -> bool
|
|||||||
|
|
||||||
pub fn fe_isnegative(f: &FieldElement) -> bool
|
pub fn fe_isnegative(f: &FieldElement) -> bool
|
||||||
{
|
{
|
||||||
let mut s = [0; 32];
|
let s = f.to_bytes();
|
||||||
fe_tobytes(&mut s, &f);
|
|
||||||
s[0] & 1 == 1
|
s[0] & 1 == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,13 +75,12 @@ impl ED25519Private {
|
|||||||
curve25519_scalar_mask(&mut result.private);
|
curve25519_scalar_mask(&mut result.private);
|
||||||
let mut a = Point::new();
|
let mut a = Point::new();
|
||||||
x25519_ge_scalarmult_base(&mut a, &result.private);
|
x25519_ge_scalarmult_base(&mut a, &result.private);
|
||||||
a.encode_to(&mut result.public);
|
result.public.copy_from_slice(&a.encode());
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign(&self, msg: &[u8]) -> Vec<u8>
|
pub fn sign(&self, msg: &[u8]) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut signature_r = [0u8; 32];
|
|
||||||
let mut signature_s = [0u8; 32];
|
let mut signature_s = [0u8; 32];
|
||||||
|
|
||||||
let mut ctx = Sha512::new();
|
let mut ctx = Sha512::new();
|
||||||
@@ -95,7 +94,7 @@ impl ED25519Private {
|
|||||||
println!("ME:r.y: {:?}", r.y);
|
println!("ME:r.y: {:?}", r.y);
|
||||||
println!("ME:r.z: {:?}", r.z);
|
println!("ME:r.z: {:?}", r.z);
|
||||||
println!("ME:r.t: {:?}", r.t);
|
println!("ME:r.t: {:?}", r.t);
|
||||||
r.encode_to(&mut signature_r);
|
let signature_r = r.encode();
|
||||||
println!("ME:signature_r: {:?}", signature_r);
|
println!("ME:signature_r: {:?}", signature_r);
|
||||||
let hram_digest = eddsa_digest(&signature_r, &self.public, &msg);
|
let hram_digest = eddsa_digest(&signature_r, &self.public, &msg);
|
||||||
let hram = digest_scalar(&hram_digest);
|
let hram = digest_scalar(&hram_digest);
|
||||||
@@ -139,9 +138,8 @@ impl ED25519Public {
|
|||||||
let h = digest_scalar(&h_digest);
|
let h = digest_scalar(&h_digest);
|
||||||
let mut r = Point2::new();
|
let mut r = Point2::new();
|
||||||
ge_double_scalarmult_vartime(&mut r, &h, &a, &signature_s);
|
ge_double_scalarmult_vartime(&mut r, &h, &a, &signature_s);
|
||||||
let mut r_check = [0; 32];
|
let r_check = r.encode();
|
||||||
r.encode_to(&mut r_check);
|
signature_r.to_vec() == r_check
|
||||||
signature_r == r_check
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,9 +95,9 @@ impl Point {
|
|||||||
return Some(Point{ x: hx, y: hy, z: hz, t: ht });
|
return Some(Point{ x: hx, y: hy, z: hz, t: ht });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_to(&self, target: &mut [u8])
|
pub fn encode(&self) -> Vec<u8>
|
||||||
{
|
{
|
||||||
into_encoded_point(target, &self.x, &self.y, &self.z);
|
into_encoded_point(&self.x, &self.y, &self.z)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invert(&mut self)
|
pub fn invert(&mut self)
|
||||||
@@ -173,9 +173,9 @@ impl Point2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_to(&self, target: &mut [u8])
|
pub fn encode(&self) -> Vec<u8>
|
||||||
{
|
{
|
||||||
into_encoded_point(target, &self.x, &self.y, &self.z);
|
into_encoded_point(&self.x, &self.y, &self.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1840,19 +1840,18 @@ pub fn curve25519_scalar_mask(a: &mut [u8])
|
|||||||
// });
|
// });
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
fn into_encoded_point(bytes: &mut [u8], x: &FieldElement, y: &FieldElement, z: &FieldElement)
|
fn into_encoded_point(x: &FieldElement, y: &FieldElement, z: &FieldElement) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut x_over_z = FieldElement::new();
|
let mut x_over_z = FieldElement::new();
|
||||||
let mut y_over_z = FieldElement::new();
|
let mut y_over_z = FieldElement::new();
|
||||||
assert!(bytes.len() >= 32);
|
|
||||||
|
|
||||||
let recip = fe_invert(z);
|
let recip = fe_invert(z);
|
||||||
fe_mul(&mut x_over_z, x, &recip);
|
fe_mul(&mut x_over_z, x, &recip);
|
||||||
fe_mul(&mut y_over_z, y, &recip);
|
fe_mul(&mut y_over_z, y, &recip);
|
||||||
fe_tobytes(bytes, &y_over_z);
|
let mut bytes = y_over_z.to_bytes();
|
||||||
let sign_bit = if fe_isnegative(&x_over_z) { 1 } else { 0 };
|
let sign_bit = if fe_isnegative(&x_over_z) { 1 } else { 0 };
|
||||||
|
|
||||||
// The preceding computations must execute in constant time, but this
|
// The preceding computations must execute in constant time, but this
|
||||||
// doesn't need to.
|
// doesn't need to.
|
||||||
bytes[31] ^= sign_bit << 7;
|
bytes[31] ^= sign_bit << 7;
|
||||||
|
bytes
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user